Skip to content

Commit 13393cc

Browse files
committed
addead readme for memo and useMemo
1 parent 828ac1f commit 13393cc

File tree

1 file changed

+287
-0
lines changed

1 file changed

+287
-0
lines changed

docs/basic/getting-started/memo.md

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
# React.memo and useMemo
2+
3+
## React.memo
4+
5+
`React.memo` is a higher-order component (HOC) that optimizes the performance of functional components by preventing unnecessary re-renders. It works by memoizing the component and only re-renders it when its props change.
6+
7+
### Why Use `React.memo`?
8+
9+
In React, when a parent component re-renders, all its child components also re-render by default, even if their props haven't changed. This can lead to performance issues in large applications or components that are expensive to re-render.
10+
11+
`React.memo` prevents these unnecessary re-renders by memoizing the component and only allowing it to re-render when its props actually change.
12+
13+
### Example Without `React.memo`
14+
15+
`typescript`
16+
17+
```bash
18+
import React from 'react';
19+
20+
interface MyComponentProps {
21+
name: string;
22+
}
23+
24+
const MyComponent: React.FC<MyComponentProps> = ({ name }) => {
25+
console.log('Component rendered');
26+
return <div>Hello, {name}!</div>;
27+
};
28+
29+
const ParentComponent: React.FC = () => {
30+
const [count, setCount] = React.useState<number>(0);
31+
32+
return (
33+
<div>
34+
<button onClick={() => setCount(count + 1)}>Increment</button>
35+
<MyComponent name="John" />
36+
</div>
37+
);
38+
};
39+
40+
export default ParentComponent;
41+
```
42+
43+
In this example, every time the button is clicked and the `count` state changes, `MyComponent` re-renders even though its `name` prop hasn't changed.
44+
45+
### Example With `React.memo`
46+
47+
`typescript`
48+
49+
```bash
50+
import React from 'react';
51+
52+
interface MyComponentProps {
53+
name: string;
54+
}
55+
56+
const MyComponent: React.FC<MyComponentProps> = React.memo(({ name }) => {
57+
console.log('Component rendered');
58+
return <div>Hello, {name}!</div>;
59+
});
60+
61+
const ParentComponent: React.FC = () => {
62+
const [count, setCount] = React.useState<number>(0);
63+
64+
return (
65+
<div>
66+
<button onClick={() => setCount(count + 1)}>Increment</button>
67+
<MyComponent name="John" />
68+
</div>
69+
);
70+
};
71+
72+
export default ParentComponent;
73+
74+
```
75+
76+
By using `React.memo`, `MyComponent` only re-renders if its `name` prop changes, improving performance by avoiding unnecessary re-renders.
77+
78+
## How `React.memo` Works
79+
80+
`React.memo` performs a shallow comparison of the component's props. If the props are the same as the previous render, the component will not re-render.
81+
82+
Primitives (numbers, strings, booleans) are compared by value.
83+
Objects, arrays, and functions are compared by reference.
84+
Custom Comparison Function
85+
If you need more control over how the props are compared, you can pass a custom comparison function as the second argument to `React.memo`.
86+
87+
### Example With `Custom Comparison`
88+
89+
`typescript`
90+
91+
```bash
92+
import React from 'react';
93+
94+
interface MyComponentProps {
95+
name: string;
96+
info: {
97+
age: number;
98+
};
99+
}
100+
101+
const MyComponent: React.FC<MyComponentProps> = React.memo(
102+
({ name, info }) => {
103+
console.log('Component rendered');
104+
return (
105+
<div>
106+
<p>Hello, {name}!</p>
107+
<p>Age: {info.age}</p>
108+
</div>
109+
);
110+
},
111+
(prevProps, nextProps) => {
112+
return prevProps.name === nextProps.name && prevProps.info.age === nextProps.info.age;
113+
}
114+
);
115+
116+
const ParentComponent: React.FC = () => {
117+
const [count, setCount] = React.useState<number>(0);
118+
const info = { age: 25 };
119+
120+
return (
121+
<div>
122+
<button onClick={() => setCount(count + 1)}>Increment</button>
123+
<MyComponent name="John" info={info} />
124+
</div>
125+
);
126+
};
127+
128+
export default ParentComponent;
129+
```
130+
131+
Here, the custom comparison function ensures `MyComponent` only re-renders when the `name` or `info.age` changes.
132+
133+
## useMemo
134+
135+
`useMemo` is a React hook that optimizes performance by memoizing the result of a calculation or a function call. It recomputes the value only when one of its dependencies changes.
136+
137+
### Why Use useMemo?
138+
139+
Without `useMemo`, expensive calculations inside a component will be recalculated every time the component renders, even if the inputs to the calculation haven't changed. This can lead to performance issues.
140+
141+
By using `useMemo`, you can memoize the result of the calculation and avoid unnecessary recalculations.
142+
143+
### Example Without `useMemo`
144+
145+
`typescript`
146+
147+
```bash
148+
import React from 'react';
149+
150+
const calculateValue = (num: number): number => {
151+
console.log('Expensive calculation');
152+
return num * 2;
153+
};
154+
155+
interface MyComponentProps {
156+
num: number;
157+
}
158+
159+
const MyComponent: React.FC<MyComponentProps> = ({ num }) => {
160+
const value = calculateValue(num);
161+
162+
return <div>Value: {value}</div>;
163+
};
164+
165+
const ParentComponent: React.FC = () => {
166+
const [count, setCount] = React.useState<number>(0);
167+
168+
return (
169+
<div>
170+
<button onClick={() => setCount(count + 1)}>Increment</button>
171+
<MyComponent num={5} />
172+
</div>
173+
);
174+
};
175+
176+
export default ParentComponent;
177+
```
178+
179+
In this example, `calculateValue` is called every time `ParentComponent` renders, even though `num` remains the same.
180+
181+
### Example Without `useMemo`
182+
183+
`typescript`
184+
185+
```bash
186+
import React from 'react';
187+
188+
const calculateValue = (num: number): number => {
189+
console.log('Expensive calculation');
190+
return num * 2;
191+
};
192+
193+
interface MyComponentProps {
194+
num: number;
195+
}
196+
197+
const MyComponent: React.FC<MyComponentProps> = ({ num }) => {
198+
const value = React.useMemo(() => calculateValue(num), [num]);
199+
200+
return <div>Value: {value}</div>;
201+
};
202+
203+
const ParentComponent: React.FC = () => {
204+
const [count, setCount] = React.useState<number>(0);
205+
206+
return (
207+
<div>
208+
<button onClick={() => setCount(count + 1)}>Increment</button>
209+
<MyComponent num={5} />
210+
</div>
211+
);
212+
};
213+
214+
export default ParentComponent;
215+
```
216+
217+
In this example, `calculateValue` is only called when `num` changes, thanks to `useMemo`.
218+
219+
## How useMemo Works
220+
221+
useMemo memoizes the result of the function passed to it. It takes two arguments:
222+
223+
1. A function that returns the value you want to memoize.
224+
2. A dependency array. The function is only recomputed when one of the dependencies changes.
225+
226+
### Example With `Dependency Array`
227+
228+
`typescript`
229+
230+
```bash
231+
import React from 'react';
232+
233+
const calculateValue = (num: number, multiplier: number): number => {
234+
console.log('Expensive calculation');
235+
return num * multiplier;
236+
};
237+
238+
const MyComponent: React.FC = () => {
239+
const [num, setNum] = React.useState<number>(5);
240+
const [multiplier, setMultiplier] = React.useState<number>(2);
241+
242+
const value = React.useMemo(() => calculateValue(num, multiplier), [num, multiplier]);
243+
244+
return (
245+
<div>
246+
<button onClick={() => setNum(num + 1)}>Increment Num</button>
247+
<button onClick={() => setMultiplier(multiplier + 1)}>Increment Multiplier</button>
248+
<div>Value: {value}</div>
249+
</div>
250+
);
251+
};
252+
253+
export default MyComponent;
254+
```
255+
256+
In this example, `calculateValue` is only called when either `num` or `multiplier changes`.
257+
258+
## Conclusion
259+
260+
Both `React.memo` and `useMemo` are useful performance optimization tools in React.
261+
262+
- Use `React.memo` to prevent unnecessary re-renders of child components by memoizing them.
263+
- Use useMemo to memoize expensive calculations or function results to avoid recalculating on every render.
264+
265+
## References
266+
267+
- React.memo Documentation (https://reactjs.org/docs/react-api.html#reactmemo)
268+
- useMemo Documentation (https://reactjs.org/docs/hooks-reference.html#usememo)
269+
270+
## Additional Resources
271+
272+
### Medium Articles:
273+
274+
- Memoization in React (https://medium.com/@rumeysakaragoz18/memoization-in-react-memo-usecallback-and-usememo-69b1367041e0)
275+
- React Performance Optimization using React.memo or useMemo (https://medium.com/@arunsheoran90/react-performance-optimisation-using-react-memo-usememo-6edcb25a1ed6)
276+
277+
### Walkthrough Videos:
278+
279+
- Learn useMemo and React Memo for Faster Apps: (https://www.youtube.com/watch?v=6-BfMpTT2PE​).
280+
281+
- useMemo Explained | React Hooks useMemo Tutorial: (https://www.youtube.com/watch?v=oR8gUi1LfWY​)
282+
283+
- Mastering React Memo:( https://www.youtube.com/watch?v=DEPwA3mv_R8)
284+
285+
- Learn useMemo In 15 Minutes - React Hooks Explained: (https://www.youtube.com/watch?v=JvdxYsF66K4​)
286+
287+
- React.memo, useMemo, and useCallback Optimizations: (https://www.youtube.com/watch?v=4BranN3qnDU​)

0 commit comments

Comments
 (0)