This is the fifth day of my participation in the August More Text Challenge. For details, see “August More Text Challenge”.

Hooks are a new feature in React 16.8 that lets us use state in functional components

Why?Hook?

Reuse state logic between components

React is a JavaScript library for building user interfaces that make it easy to create interactive UI views declaratively and componentized. It’s really focused on the UI.

Reuse of component state is often done with providers, consumers, render props, and higher-order components, which can be difficult if you need to organize or refactor code. This is why redux is popular in the medium and large scale projects. To address this pain point of sharing state logic, hooks give you a more native way to reuse state logic without having to modify the component structure.

The most common way to do this is to extract some common logical state into a custom hook:

function useLoadingStatus(fetch) {
  const [isLoading, setIsLoading] = useState(null);

  // ...

  return isLoading;
}
Copy the code

Component complexity is high and difficult to split into small particles

In class components, we need to use a large number of lifecycle functions, such as componentDidUpdate, componentDidMount, etc., it is very difficult to split complex code, and it is easy to produce bugs, most of the time, it is difficult to break a component into many small components. Even using the state management library of the Redux class. It is to solve this problem that hooks break down the interrelated parts of the component into smaller letters, such as setting subscription or request data, rather than forcing a lifecycle partition. At the same time, we can also use reducer to manage the internal state, which makes the state more predictable.

More often than not, we can use multiple UseEffects to separate different logic, as long as we maintain their respective dependencies ([]).

Here is a countdown control I made myself:

/** ** @param {amountTime} @param {idx} @param {amountTime} @param {idx} idx, handleSubmit }) { const [time, setTime] = useState(amountTime); useEffect(() => { setTime(amountTime); }, [idx, amountTime]); useEffect(() => { if(time === 0){ handleSubmit && handleSubmit(1); return; } const timer = setTimeout(() => { if (time > 0) { setTime(time - 1); } else { handleSubmit(); }}, 1000); // eslint-disable-next-line consistent-return return () => timer && clearTimeout(timer); }, [time]); return <Text style={styles.amountNumber}>{time}s</Text>; }Copy the code

The commonly usedHook

useState

The useState() function is similar to the class component’s state and setState() functions, which allow us to useState in functional components.

const [state, setState] = useState(initialState); There is also an lazy initialization that relies on props to initialize state. InitialState is only used for the initial rendering of a component and is ignored for subsequent rendering. const [state, setState] = useState(() => { const initialState = someExpensiveComputation(props); return initialState; });Copy the code

To update state, simply call setState(newState) at the appropriate time.

There is also a common update computed by a function: the new state value needs to be computed from the current value

setState(state => state + 1)

useEffect

UseEffect’s mental model is different from componentDidMount and other lifecycle functions. Its mental model is closer to state synchronization than to responding to life cycle events

The function passed to useEffect is called in a delayed event after the browser finishes the layout and drawing, but it is always executed before any new rendering. UseLayoutEffect is similar to useEffect, but it calls Effect synchronously to trigger a rerendering after all the DOM layouts have been completed. It’s usually used to get the position of an element, like the value of scroll.

The useEffect function returns only one of the side effects that need to be removed during component uninstallation.

The second useEffect argument accepts an array as a dependency for its re-execution. Only if the values in the array change will the re-execution be carried out.

See this useEffect guide

useCallback

We usually put a callback function and callback dependency into useCallback, which returns a memoized callback function and re-executes the callback function when the callback dependency changes.

Here’s a common performance optimization:

When the parent method is passed to the child using props, we wrap the parent method with the useCallback hook and set the hook dependency to [] null. This can reduce the rerender times of the child component.

UseCallback (fn, deps) equals useMemo(() => fn, deps).

useMemo

It works a little bit like the useCallback. Pass an array of functions and dependencies to useMemo as arguments, and it returns a memoized value. It is also a rendering performance optimization, where functions passed to useMemo are executed during rendering.

If an array of dependencies is not provided, useMemo evaluates the new values each time it renders.

useRef

UseRef returns a mutable ref object whose.current property is initialized to the passed parameter (initialValue). The returned REF object persists throughout the lifetime of the component. Usually as a way to access the DOM

const refInput = useRef(null); . . return( <input ref={(r) => refInput = r} type="text" /> )Copy the code

When the content of the ref object changes, the.current property is changed, but the component is not rerendered. So sometimes it can be used to store extra data.

react HooksPerformance optimization

To reduceRerender number

When the parent component’s re-property update triggers a re-render, the child component is also re-rendered

  1. There is no change in the property of our child component, and we do not want the child component to be rerendered, we can use the child componentmemoPackage the child components.
  2. When the parent component method passespropsWhen passed to a child component, use it only for the child componentmemoNo, we need to pass the parent’s methoduseCallbackSet the hook dependencies to[]Empty dependency.

To reduceRerender complexity

Use memoize-one to reduce data calculations

const add = (a, b) => a + b;
const memoizedAdd = memoizeOne(add);
Copy the code

conclusion

If this article helps you, please click 👍 and pay attention to ⭐️

If there are any mistakes in this article, please correct them in the comments section 🙏🙏.