Hello, everyone. I’m Treadhole Little Planet. As a Component advocate, take a small step on the Hook and see what it is. Basic syntax and so on will not say, the article is many, this is only my own in the development of the time, need to pay attention to the point ~ [TOC]

About the state of

  1. useStateManaging state, one thing to note here,When you use the set method of useState, the old state is not automatically merged into the new state, that is, the set changes the full data.

    If your state is an object, you need to manually compose the entire new data
Const [obj,setObj] = useState({name: "mushroom ",age: 0}); // Update setObj({... Obj, name: "big mushroom"}); {name: "big mushroom ",age: 0}Copy the code
  1. The state generated by useState, as a constant in the function, is plain data, and there is no data binding to force DOM updates. After calling setState, React will re-execute the render function, and that’s it. Thus, state is also a common variable under the scope of a function. We can say that each function execution has an independent state, which is Capture Value property. In short, it is not real-time.

  2. You can bypass Capture Value features with useRef. Ref can be thought of as a unique reference in all Render processes, so all assignments or values to ref get only one final state, without isolation between Render processes. The reason is that ref.current will be given an initialValue and will not change after that. But you can set the value yourself. Setting its value does not retrigger the render function. So in addition to retrieving DOM nodes, useRef has a powerful use for caching data because it does not trigger function updates; Modules such as connectAdvanced in the React-Redux source code use this skill

function Example() {
  const [count, setCount] = useState(0);
  // Initial ref
  const latestCount = useRef(count);

  useEffect(() => {
    // Set the mutable latest value
    latestCount.current = count;
    setTimeout(() => {
      // Read the mutable latest value
      console.log(`You clicked ${latestCount.current} times`);
    }, 3000);
  });
  // ...
}
Copy the code

The life cycle

The main benefit of Component is that it has a life cycle for processing various data, which can also be simulated in hooks using Effect hooks

  1. Usually we use component lifecycle functions to perform some side effects, but usually side effects logic is complex and may be buggy, so in Hook, it is recommendedUse a separate Effect hook for each piece of logic
UseEffect (() => {console.log(' componentDidMount'); Return () => {console.log(' Analog componentWillUnmount')}}, []); UseEffect (() => {console.log(' componentDidMount and name change, componentDidUpdate'); Return () => {console.log(' effect')}}, [name]); return () => {console.log(' effect')}}, [name]);Copy the code
  1. For useEffect, the time to execute is after all the DOM changes have been made and the browser has rendered the page, React (componentDidMount, componentDidUpdate); React (componentDidMount, componentDidUpdate);

  2. Use useMemo to reduce unnecessary rendering

function Parent({ a, b }) {
  // Only re-rendered if `a` changes:
  const child1 = useMemo(() => <Child1 a={a} />, [a]);
  // Only re-rendered if `b` changes:
  const child2 = useMemo(() => <Child2 b={b} />, [b]);
  return (
    <>
      {child1}
      {child2}
    </>
  )
}
Copy the code

Special scenario

  1. Depend on some value, but do not execute the callback after initialization, do not execute the callback after the dependency changes, simulatecomponentDidUpdate
const init = useRef(true);
useEffect(() => {
  if (init.current) {
    init.current = false;
    return;
  }
  // do something...
}, [ xxx ]);

Copy the code
  1. Use hooks in loops/judgments

Never call hooks in loops, conditions, or nested functions. Make sure you always call them at the top of your React function

That’s what the official document says. The reality is that since hooks are registered based on a linked list, there is a fixed order that, if you use judgments or loops, will result in a different order of execution. Color {#FF7F50}{my understanding} is that it is ok to use a Hook in a condition or loop as long as the execution order is fixed.

  useEffect(() => {
    func1();
    func2(a);
  }, [a]);
  
  useEffect(() => {
    func1();
    func2(b);
  }, [b]);
  
  useEffect(() => {
    func1();
    func2(c);
  }, [c]);
Copy the code

In the example above, you can see that there is too much repeating code, so you can use a loop to perform userEffect

  const arr = [a,b,c];
  for (let i of arr){
    useEffect(() => {
      func1();
      func2(i);
    }, [i]);
  }
Copy the code
  1. userEffectUse asynchronous functions in

UseEffect cannot be used directly with async await

To use this function, write it as an immediate function or useEffect after creating an asynchronous function

useEffect(() => { // Using an IIFE (async function asyncFunction() { await loadContent(); }) (); } []);Copy the code
useEffect(() => { const asyncFunction = async () =>{ const data = await loadContent(); setData(data) } asyncFunction(); } []);Copy the code

Matters needing attention

  • useLayoutEffectMay block the browser’s drawing

    UseEffect execution order: Component update mount complete -> Browser DOM drawing complete -> Execute useEffect callback

    UseLayoutEffect execution order: Component update mount complete -> Execute useLayoutEffect callback -> Browser DOM drawing complete
  • Never call a Hook in a loop, condition, or nested function. You must always use the Hook at the top of the React function. This is because React needs to use the call order to properly update the corresponding state and call the corresponding hook functions. Once a Hook is called in a loop or conditional branch statement, it is easy to cause inconsistencies in the order of calls, with unpredictable consequences.
  • You can only use hooks in React functional components or custom hooks
  • You can install the ESLint plug-ineslint-plugin-react-hooksAdd the configuration to.eslintrc.js
{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error"
  }
}
Copy the code
  • Be careful to place logically related states within the same useEffect Dependences in multiple Useeffects
  • When using a caching API like useMemo, you need to put the state value it depends on in the second parameter, or you may not get the latest state