Memo(), useCallback(), useMemo() usage scenarios
When the props or state of the parent component change, the render re-renders, but the props passed to the child component do not change. As he said, he simply called the child component, and the child component also needs to be re-rendered, which leads to unnecessary rendering of the component
()
When the parent component simply calls the child component and does not pass any attributes to the child component, we can control the rendering of the function component through memo
()
Taking the component as a parameter to the function (memo), the return value (Child) of the function is a new component.
import { useState } from "react"; import { Child } from "./child"; export const Parent = () => { const [count, setCount] = useState(0); const increment = () => setCount(count + 1); return ( <div> <button onClick={increment}>Number of clicks:{count}</button> <Child /> </div> ); };
import {memo} from 'react' export const Child=memo(()=>{ ('Rendered') return <div>Subcomponents</div> }) //Use the component wrapped after memo(), when the Parent component is re-rendered and updated, the Child component does not re-render and update.
When we pass the value to the child component, using the memo function will not work for the update of the control component.
Parent component
import { useState } from "react"; import { Child } from "./child"; export const Parent = () => { const [count, setCount] = useState(0); const [name, setName] = useState("Xiao Ming"); const increment = () => setCount(count + 1); const onClick = (name: string) => { setName(name); }; return ( <div> <button onClick={increment}>Number of clicks:{count}</button> <Child name={name} onClick={onClick} /> </div> ); };
Subcomponents
import { memo } from "react"; export const Child = memo( (props: { name: string; onClick: (value: any) => void }) => { const { name, onClick } = props; ("Rendered", name, onClick); return ( <> <div>Subcomponents</div> <button onClick={() => onClick("Little Red")}>Change name value</button> </> ); } );
The reasons for this result:
When clicking the parent component button, the parent component's count is changed, causing the parent component to re-render.
When the parent component is re-rendered, the onClick function is re-created, causing the onClick property passed to the child component to change, causing the child component to re-render.
If only the basic data type passed to the child component will not be re-rendered
Note: If used directlyuseState
The deconstructed setName is passed to the child component, and the child component will not be rendered repeatedly because the deconstructed function is a memoized function.
()
So, in this case we use() useCallback(fn, deps)
import { useCallback, useState } from "react"; import { Child } from "./child"; export const Parent = () => { const [count, setCount] = useState(0); const [name, setName] = useState("Xiao Ming"); const increment = () => setCount(count + 1); //The callback function wrapped with the useCallback hook is the memoized function. When it first calls the function, it caches the parameters and calculation results. When calling this function again, if the second parameter dependency does not change, it will directly return the cache result and will not be re-rendered. const onClick = useCallback((name: string) => { setName(name); }, []); return ( <div> <button onClick={increment}>Number of clicks:{count}</button> <Child name={name} onClick={onClick} /> </div> ); };
But when the attribute name we pass is not a string, but an object
Parent component
import { useCallback, useState } from "react"; import { Child } from "./child"; export const Parent = () => { const [count, setCount] = useState(0); // const [userInfo, setUserInfo] = useState({ name: "Xiao Ming", age: 18 }); const increment = () => setCount(count + 1); const userInfo = { name: "Xiao Ming", age: 18 }; return ( <div> <button onClick={increment}>Number of clicks:{count}</button> <Child userInfo={userInfo} /> </div> ); };
Subcomponents
import { memo } from "react"; export const Child = memo( (props: { userInfo: { name: string; age: number } }) => { const { userInfo } = props; ("Rendered", userInfo); return ( <> <div>name: {}</div> <div>age:{}</div> </> ); } );
Click on the parent component count and see that the child component has been re-rendered every time. The analysis reason is the same as calling a function:
- Click the parent component button to trigger the parent component to re-render;
- Parent component rendering,
const userInfo = { name: "Xiao Ming", age: 18 };
A row will regenerate a new object, causing the userInfo attribute value to be passed to the child component to change, which in turn causes the child component to be rerendered. - Note: If using
useState
The deconstructed userInfo subcomponent will not be rendered repeatedly because the deconstructed value is a memoized value.
At this time we use () useMemo(() => fn, dep)
()
useMemo() returns a memoized value.
If no dependency array is provided,useMemo
A new value is calculated every time you render.
import { useMemo, useState } from "react"; import { Child } from "./child"; export const Parent = () => { const [count, setCount] = useState(0); // const [userInfo, setUserInfo] = useState({ name: "Xiao Ming", age: 18 }); const increment = () => setCount(count + 1); const userInfo = useMemo(() => ({ name: "Xiao Ming", age: 18 }), []); return ( <div> <button onClick={increment}>Number of clicks:{count}</button> <Child userInfo={userInfo} /> </div> ); };
Compare useCallback() and useMemo()
useCallback(fn, deps) returns the callback functionmemoized callback function
const onClick = useCallback((name: string) => { setName(name); }, []);
useMemo(() => fn, dep) returns a memoized value.
const userInfo = useMemo(() => ({ name: "Xiao Ming", age: 18 }), []);
The above is the detailed content of the function and usage scenarios of the memo useCallback useMemo method in React. For more information about React useCallback useMemo, please follow my other related articles!