1. Business scenarios
React is a javascript library used to build user interfaces. It is mainly responsible for converting data into views to ensure the consistency of data and views. React rerenders data every time data is updated to ensure the consistency of data and views. All child components mounted under the parent component are also re-rendered, because React by default renders all components, including children of children, which creates unnecessary waste.
-
Define a parent component using a class
export default class Parent extends React.Component { state = { count: 0,}render() { return( <div>I'm the parent component<button onClick={()= >This.setstate ({count: this.state.count++})}> Click the button</button> <Child /> </div>)}}Copy the code
-
2. Define a child component
class Child extends React.Component { render() { console.log('I'm a child component'); return ( <div>I'm a child component<Grandson /> </div>)}}Copy the code
-
Define a grandchild component
class Grandson extends React.Component { render() { console.log('Grandchild component') return(<div>The grandson components</div>)}}Copy the code
-
4, the above several components is the standard of the react class components, function component is also similar, when you click on the button in the parent component, but you just want to change the count value inside the parent component, but you will find that each time you click on the component and sun components will render again, because the react does not know whether to render child components, We need to judge for ourselves.
Class componentsshouldComponentUpdate
Lifecycle hook functions
-
ShouldComponentUpdate (); shouldComponentUpdate ();
If false is returned, the component is not updated. If true, the component needs to be updated
class Child extends React.Component { shouldComponentUpdate (nextProps, nextState) { console.log(nextProps, this.props); if (nextProps.count === this.props.count) { return false; } else { return true; }}... }Copy the code
Name === this.props. Name === this.props. The parent component does not pass name to the current component so the following return false component is not updated
-
2, if the child component is not updated, then the child component does not update the data
Second, the use ofPureComponet
Syntactic sugar
ShouldComponentUpdate PureComponet = shouldComponentUpdate PureComponet = shouldComponentUpdate PureComponet = shouldComponentUpdate PureComponet = shouldComponentUpdate PureComponet = shouldComponentUpdate
-
1. Inheritance in child components
class Child extends React.PureComponent { render() { console.log('I'm a child component'); return ( <div>I'm a child component<Grandson /> </div>)}}Copy the code
-
2. Use in the parent component
// The following case does not re-render the child component <Child/> // Re-render the child component in the following case <Child count={this.state.count}/> Copy the code
Three,memo
The use of
You can use the shouldComponentUpdate hook function or PureComponent inheritance to not render a child component if the child component is a class component, but you can’t use these methods for function components. React provides the Memo for function components to wrap around them and render them unnecessarily.
-
1. Component definitions (class components can also be used here)
function Child () { console.log('I'm a child component'); return ( <div>Child components</div>)}function Parent () { const [count, setCount] = useState(0); return ( <div>I am the parent component -{count}<button onClick={()= >SetCount (count + 1)}> Click the button</button> <Child /> </div>)}Copy the code
-
2. In this case, the parent component’s internal change count is not passed to the child component, but the child component is rerendered as well, which is not desirable because we need to wrap the child component
function Child () { console.log('I'm a child component'); return ( <div>Child components</div>)}const ChildMemo = React.memo(Child); function Parent () { const [count, setCount] = useState(0); return ( <div>I am the parent component -{count}<button onClick={()= >SetCount (count + 1)}> Click the button</button>{/* In this case, child components are not rendered */}<ChildMemo />{/* Render child components in this case */}<ChildMemo count={count}/> </div>)}Copy the code
Four,useMemo
anduseCallback
The understanding of the
-
1. UseMemo and useCallback both have the function of caching, but they are different cache objects, one is an attribute, the other is a cache function, the characteristics are both, when the cache dependency does not change, to obtain or obtain the cache
-
2. UseMemo wraps attributes in function components and returns a cached new attribute. If the dependent attribute has not changed, the new attribute will be retrieved from the cache.
-
UseCallback is a cache of methods in a function component and returns a cached method
Five,useMemo
(We rely on borrowing subcomponent updates to do this)
-
1. According to the above method, we update the data in the parent component and observe the changes in the child component
const Child = (props) = > { console.log('Rerender child components', props); return ( <div>Child components</div>)}const ChildMemo = React.memo(Child); const Parent = () = > { const [count, setCount] = useState(0); const [number, setNumber]=useState(0) const userInfo = { age: count, name: 'hello',}const btnHandler = () = > { setNumber(number+1); } return ( <div> {number}-{count} <button onClick={btnHandler}>button</button> <ChildMemo userInfo={userInfo}/> </div>)}Copy the code
We only update the value of number. The value of the object passed to the child component does not change, but each time the child component is updated, even though we use the react. memo wrapper on the child component, this is because every time we re-render in the parent component, the object will be a new object. So the child component is updated again,
-
2. Use useMemo to wrap attributes
const userInfo = useMemo(() = > { return { age: count, name: 'hello'}; }, [count]);Copy the code
After using useMemo packaging object, return a new object of cache effect, said the second parameter dependency, or observation of objects, when observed no change, return is the cache object, if observed changes, so it will return a new, now, no matter how you update the number of values, the child components will not update again
-
Note :useMemo must be used in conjunction with react. memo, otherwise it will not work if passed to child components
Vi.useCallback
The use of
As mentioned earlier, useCallback is a wrapper around a method that returns a method with a cache. A common usage scenario is for a parent component to pass a method to a child component
-
1. When not using useCallback
const Child = (props) = > { console.log('Rendered child component'); const { onClick } = props; return ( <button onClick={onClick}>Click the button to get the value</button>)}const ChildMemo = React.memo(Child); const Parent = () = > { const [text, updateText] = useState(' '); const textRef = useRef(text); const handleSubmit = () = > { console.log('Current value', text); } return( <div>I'm the parent component<input type="text" value={text} onChange={(e)= > updateText(e.target.value)}/> <ChildMemo onClick={handleSubmit}/> </div>)}Copy the code
The result is that every time a value is entered in the input box, the child component is re-rendered. In fact, the child component is just a button that gets the final input value. Every time the parent component enters a value, the child component is updated
-
Use useCallback to wrap a method
const Parent = () = > { const [text, updateText] = useState(' '); const textRef = useRef(); // useCallback relies on textRef changes to get the latest data const handleSubmit = useCallback(() = > { console.log('Current input field value :', textRef.current); }, [textRef]) // The textRef current is reassigned when the value of text changes useEffect(() = > { textRef.current = text; }, [text]); return( <div>I'm the parent component<input type="text" value={text} onChange={(e)= > updateText(e.target.value)}/> <ChildMemo onClick={handleSubmit}/> </div>)}Copy the code