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 Hooks
Performance optimization
To reduceRerender number
When the parent component’s re-property update triggers a re-render, the child component is also re-rendered
- 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 component
memo
Package the child components. - When the parent component method passes
props
When passed to a child component, use it only for the child componentmemo
No, we need to pass the parent’s methoduseCallback
Set 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 🙏🙏.