preface
By default, the parent component’s state changes and it rerenders not only itself but also its children. So React invented useMemo & useCallback to help you cut down on unnecessary renderings.
In addition, shouldComponentUpdate/React.pureComponent/React.memo does something similar.
useMemo
const UseMemoPage = props= > {
const [counter, setCounter] = useState(0)
const [value, setValue] = useState(' ')
const total = () = > {
console.log('computed')
let result = 0
for (let i = 0; i < counter; i++) {
result += i
}
return result
}
console.log(UseMemoPage.name, 'render')
return (<>
<p>{value}</p>/* When you change the value of the input, it also triggers an unnecessary operation of total, */<input value={value} onChange={(e)= > setValue(e.target.value)} />
{total()}
<button onClick={()= > setCounter(counter + 1)}>add</button>
</>)}// console.log UseMemoPage render
// console.log computed
Copy the code
- With useMemo improvements, changes to value do not trigger recalculation
In addition, useMemo can return a React component, which has the same effect
const total = useMemo(() = > {
console.log('computed')
let result = 0
for (let i = 0; i < counter; i++) {
result += i
}
return result
}, [counter])
// console.log UseMemoPage render
Copy the code
useCallback
const UseCallbackPage = props= > {
const [counter, setCounter] = useState(0)
const [value, setValue] = useState(' ')
const addClick = () = > {
console.log(addClick.name, 'render')
setCounter(state= > state + 1)}console.log(UseCallbackPage.name, 'render')
return (<>
<p>{value}</p>
<input value={value} onChange={(e)= > setValue(e.target.value)} />
<button onClick={()= > setCounter(counter + 1)}>add</button>
<Child counter={counter} addClick={addClick}></Child>
</>)}const Child = React.memo((props) = > {
console.log('Child'.'render')
return (<div onClick={props.addClick}>{props.counter}</div>)})// console.log UseMemoPage render
// console.log Child render
Copy the code
- If you use react.memo, however, when the value is updated, it will generate a new addClick(just the same name), which will render the Child component. This is when the useCallback comes into play, which will cache your function
const addClick = useCallback(() = > {
console.log(addClick.name, 'render')
setCounter(state= > state + 1)}, [])// console.log UseCallbackPage render
Copy the code
Conclusion:
- UseCallback, useMemo looks like a patch for React, but it works fine
Reduce unnecessary rendering
- UseMemo returns an object, which generally applies to the component itself
- UseCallback returns a function that can be used with React. Memo to reduce Child rendering
- Therefore, the subcomponents should be as stateless as possible to facilitate development/testing/optimization