The key to the program is to learn ideas. Record hooks related to facilitate later worry.

1. Differences between hooks and class components or function Components

React says UI is a view map of data, V = f(props,state); The f function processes and processes the input data. Compared to a traditional class component, a class component:

  1. The compiler is larger
  2. This points to the question
  3. The reusability is poor

Hooks can be understood as independent function components that can self-render. It is also a change in the thinking of programming code, as shown below: a reflection of views and changes.

This core idea will be reflected in the API below.

2. Use hooks

2.1 State: setState

const [counyt,setCount] = useState(0); It describes how states and behaviors are reflected in the HOOKS API. React automatically helps us bind data.

The function will re-render each time the state count changes. Each function call is an independent individual, reflected in the underlying data structure of a list, that is, every time render will insert a node in the list.

function Example() {
  const [count, addCount] = useCount(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={()= > addCount()}>
        Click me
      </button>
    </div>
  );
}
Copy the code

You can also use custom hooks named after the business call,addCount instead of the system setCount. x

function useCount(initData){
   const [count,setCount] = useState(initData);
   return [count,() = >{
     setCount(count +1)}}]// example
  const [count, addCount] = useCount(0);
Copy the code

2.2 role effect

   // Example
   useEffect(() = > {
      console.log('useffect')
      document.title = `You clicked ${count} times`;
   },[count]);
Copy the code

Each time the Example function is executed, a useEffect is created. Or we can use custom hooks to encapsulate the data decoupling UI. Hooks advocate fine-grained control to better match semantics and behavior. Make the effect descriptive.

function useCount(initData){
   const [count,setCount] = useState(initData);
   return [count,() = >{
     setCount(count +1)}}]function log(count){
  console.log('xxxxxx',count);
}

// Example
  useEffect(log.bind(null,count),[count]);
Copy the code
  • effectIf you rely on an empty array, it will only be executed once, because null is always null.
  • 2. Change: This effect occurs when there is a change,
  • Each time, a new function is created, rebinding the current dependent function
  • When the function component is re-rendered, it reexecutes the entire function, including all “registered” hooks. By default, useEffect callback is also reexecuted!
  • Do not rely on less and do not pass more! Deps array entries must be mutable. They cannot be passed to an object or function

Things to watch out for.

    useInterval(() = >{
        console.log('ccc',count);
        // setCount(count+1); // Execute only once
        setCount(count= >count+1); 
    },1000)
Copy the code

Try to write it in a functional way, because there’s a little bit of a problem with the assignment.

2.3 useContext

const value = useContext(MyContext); Receives a context object (the return value of React.createcontext) and returns the current value of the context. A hooks used to share state between components.

const ThemeContext = React.createContext(themes.light);
function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
       <div>
         <ThemedButton />
      </div>
    </ThemeContext.Provider>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return (
    <button style={{ background: theme.background.color: theme.foreground}} >
      I am styled by theme context!
    </button>
  );
}
Copy the code

2.3 useReducer

Used to manage complex data structures (useState is generally used to manage the state of flat structures), basically implementing the core functionality of Redux.

// A state has multiple behaviors
function reducer(state, action) {
    switch (action.type) {
        case 'add':
            return state + 1;
        case 'red':
            return state - 1;
        default:
            console.error('sssss');
    }
    return 0;
}

export default() = > {const [count, dispatch] = useReducer(reducer,0); // The second argument can be an object or a single value
    return (
        <div>
            <p>msg is: {count} </p>
            <button onClick={()= > dispatch({type: 'add'})}>+</button>
            <button onClick={()= > dispatch({ type: 'red' })}>-</button>
        </div>)}Copy the code

2.4 useRef

  • Ref (erence)
  • refmanagementreactOther objects, we knowreactIn their ownuiBuilds a layer on its own, and React doesn’t manage it itself. Eg: Focus media operations
  • Usually with useEffect,
  • It also has another function, which is to hold some values, and this has to do with design, so this is a clever way to do it
  • Click on the buttonfocus.
function useFousInput() {
    const refInput = useRef(null); // Return a variable ref object that remains the same throughout the lifetime of the component
    // Start with a null value, that is, the value will be reached during the execution
    return (
        <div>
            <input type="text" ref={refInput} />
            <input
                type="button"
                value="foucs"
                onClick={()= >{ refInput.current.focus(); }} / ></div>
    );
};
Copy the code
  • The calculator can get the previous valuerefIs an immutable thing, especially important when function oriented. It’s hard to do a cache in a functional environment, so this reference is very useful.
function useCompute() {
    const [count, setCount] = useState(0);
    const preRef = useRef(0); 
    return (
        <div>
            <p>Current value: {count}</p>
            <p>Previous value: {preref.current}</p>
            <input type="button" onClick={()= > {
                preRef.current = count;
                setCount(count => count + 1)
            }}  value="+"/>
            <input type="button" onClick={()= > {
                preRef.current = count;
                setCount(count => count - 1)
            }} value="-"/>
        </div>
    );
}
Copy the code

This is because it creates a normal Javascript object. Instead, useRef() creates a {current:… } object, the only difference is that useRef returns the same REF object every time it is rendered. Changing the.current property does not cause the component to rerender.

3 the cache

3.1 momo

In function components, React provides an API similar to that of PureComponent and class components called React.memo, which makes a light comparison of each props item when it is re-rendered, and does not trigger rerender if the reference does not change

/** * React. Memo is used for pure functions
const MemoList = React.memo(({ list }) = > {
    return (
        <ul>
            {list.map(item => (
                <li key={item.id}>{item.content}</li>
            ))}
        </ul>
    );
},areEqual) ;


/** * return true: indicates that the component is not rendered. * return false: indicates that the component is rendered
function areEqual(prevProps, nextProps) {
    if(nextProps.seconds % 10= = =0) {return true
    }else {
        return false}}Copy the code

UseMemo is called inside a component and has access to the component’s props and state, so it has more fine-grained dependency control than react.memo

3.2 useMemo && useCallback

  • Cache a function :(useCallback)
  • Cache a value: (useMemo)

UseMemo (() => fn, deps)

UseMemo is used to cache the results of some time-consuming calculations and to re-perform the calculations only if the dependent parameters change:

Functions passed to useMemo are executed during rendering. Do not perform non-render operations inside this function. Operations such as side effects are the domain of useEffect, not useMemo.

const UseMemoExample = () = > {
    const [count, setCount] = useState(0);
    const depVal = Math.floor(count / 10);
    
    const memText = useMemo(() = > {
        return 'this is time ' + depVal +The '-'+ Date.now();
    }, [depVal]); // Always remember that dependencies change, not true or false

    return (
        <div>
            <p>mem: { memText }</p>
            <p>real value {count} </p>
            <input type="button" onClick={()= > {
                setCount(count => count + 1)
            }} value="+"/>
        </div>)}Copy the code

Cache function

const memoizedCallback = useCallback(
  () = > {
    doSomething(a, b);
  },
  [a, b],
);
Copy the code

4. Customize hooks

A custom Hook is a function whose name begins with “use”. Other hooks can be called inside the function.

This custom component actually returns a state encapsulation behavior. Inside the render function is an expression that is returned by a value. A state is enclosed by an hooks behavior.

function usePerson() {
    const [list, setList] = useState(null);
    const request = () = > {
        async function getData (){
            let res = await sleep();
            setList(res);
       }
       getData();
    }

    useEffect(request,[]);
    return list;
}
Copy the code

Custom hooks resolve the previous issue of not being able to share logic flexibly in the React component. You can create custom hooks that cover a variety of scenarios, such as form processing, animations, subscription declarations, timers, and maybe even other scenarios we didn’t think of. More importantly, creating custom hooks is as simple as using React’s built-in functionality.

Try to avoid adding abstract logic too soon. Now that function components can do so much more, the number of lines of code in the code base for function components can soar. This is normal — you don’t have to split them into hooks immediately. However, we encourage you to find possibilities by customizing hooks to simplify code logic and eliminate component clutter. eg:

function useData() {
    const [data, setData] = useState(0);
    const [loading, setLoding] = useState(false);
    // In this way, we can know the meaning by the name, which is more semantic
    const [count, addCount] = useCount(0);
    const fetchData = () = > {
        setLoding(true);
        setTimeout(() = > {
            setData(Date.now());
            setLoding(false);
        }, 3000);
    };
    return {
        loading,
        count,
        data,
        fetchData,
        addCount
    };
}
Copy the code

5 hooks use encapsulation and libraries

5.1 Decoupling encapsulation of some common functional development

Adaptive width and height hooks

function useWinSize() {
  const html = document.documentElement;
  const [ size, setSize ] = useState({ width: html.clientWidth, height: html.clientHeight });

  useEffect(() = > {
    const onSize = e= > {
      setSize({ width: html.clientWidth, height: html.clientHeight });
    };

    window.addEventListener('resize', onSize);

    return () = > {
      window.removeEventListener('resize', onSize);
    };
  }, [ html ]);

  return size;
}
Copy the code

React-use document address Chinese document