The execution timing of effect
Delay execution after the browser completes layout and paint. This design does not delay the presentation of the UI, faster presentation of the UI. Unlike the class component’s componentDidMount, this is executed before the browser draws. That’s why when Hooks first came out, some people used useEffect logging to test performance and found it slower than componentDidMount.
During any render, the props and state are always the same
This means that props and state are independent of each other in different renderings, as are any values that use them (including event handlers). They are all part of a specific render, and even asynchronous functions in event handlers use the same values as the next render. The latest status values are not used because of delays. Here’s a practical example:
function Counter () {
const [count, setCount] = useState(0)
function onBtnClick = () = >{
setTimeout(() = > {
alert('count ' + count)
}, 1000)}return (
<div>
<button onClick={()= > {setCount(count + 1)}}>{count}</button>
<button onClick={onBtnClick}>alert</button>
</div>)}Copy the code
First click button 1 3 times, then click button 2 1 times, then click button 1 2 times. What do you think the popover’s count is at the end?
If you answered 5, you’re wrong. Let’s see. When the first button is clicked 3 times in a row, count changes to 3, and onBtnClick gets count 3. When the first button is clicked again, the entire Counter function is reexecuted and onBtnClick is redefined, completely unaffected by the onBtnClick we called earlier and the count referenced in it. So the value of alert is 3.
Each time the state is updated, the entire function is re-executed, and the variables, functions, and previously defined variables are independent of each other, like different frames. It is worth noting that the count used in the DOM is simply the value of a constant after each re-execution, with no data binding, listening, proxy or other “dark technology” at all.
Effect always gets props and state from the render that defined it
How is a functional component different from a class component?
Each render has its own Effects
As with other event handlers in the component, each render produces an effect function that belongs to that render. The variables are also values from that render.
If you want to use the latest value in the effect callback instead of the currently rendered value captured, you can use refs. It is important to note that if you want to read “future” props and state in functions defined in past renderings, this approach breaks the default paradigm and can lead to code fragility. If there is an alternative to logic, use another approach.
Cleanup in effect
Effect is executed after the browser draws, and effect clearing is also delayed. The effect cleanup function in the previous component is executed after the next component is drawn to the browser and before useEffect is executed. In other words, the effect execution time of the previous component is the same as the effect execution time of the next component, but the former component is earlier. The previous component and the next component can be two different function components, or two renderings of the same function component. In the case of the same component, the cleanup function generated during the last rendering will be executed after the next rendering, but before effect.
Take a look at this code:
useEffect(() = > {
ChatAPI.subscribeToFriendStatus(props.id, handleStatusChange);
return () = > {
ChatAPI.unsubscribeFromFriendStatus(props.id, handleStatusChange);
};
});
Copy the code
What happens when the props. Id changes from 10 to 20?
- React will render the UI with id 20 first
- The browser draws the UI, and the user sees the UI with ID 20
- Clear the subscription whose ID is 10
- Run effect 20
As you can see, the UI in Hooks has a higher priority and is more focused on the user experience, which is one of hooks’ “mental models”.
So why does the cleanup function still get props with id 10? The answer is up there, and Effect always gets props and state from the render that defined it. Frame by frame function… There is a little bit of feeling
Synchronization, not life cycle
As you can see from above, Hooks are concerned with synchronization of initial render and subsequent updates, not the complex concept of a lifecycle.
React renders basically the same functions and variables, which reduces the “entropy” of the program and prevents the program from accumulating more and more change combinations with more and more states and updates, making it difficult to locate bugs. The advantage of Hooks is that each update is a restart, and without cumulative changes, the program looks much clearer.
React synchronizes changes to the Dom based on the current props and state. There is no “mount” and “update” life cycle for class components. Effect is a similar “mental model” that makes simultaneous changes outside the React Tree after the browser renders, based on the current state.
Rely on
The dependency on effect can conditionally avoid rendering and only perform it when it changes. Sometimes dependencies can be omitted in some way
- Functional update
- useReducer
[] Dependencies are closer to componentDidMount and componentWillUnmount, where you can perform a first render and uninstall logic. However, if some dependencies are still unavoidable after the above approach is tried, then some logic can only be executed in effect using conditional judgment, which may break the model of synchronous execution of functional components, but there seems to be no better way.