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 componentsshouldComponentUpdateLifecycle 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 ofPureComponetSyntactic 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,memoThe 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,useMemoanduseCallbackThe 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.useCallbackThe 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