I have been using react development for 1 year, so I can’t say I am very proficient, but in the process of using it, I did understand and summarize some tips that can speed up our subsequent development.
1. some tips in useState
When we use react to develop function comppoent, we can’t help but see
useState everywhere, so what are the pitfalls and things to watch out for in useState?
1.1 useState is asynchronous
Some developers who have been using react for a short time often write it like this: after calling the set method to set the value of the state, they immediately go and get the value.
However, when using the log output, no change is found. This is because set in useState is an asynchronous operation, while the function func is called synchronously, which causes func() to be executed before set.
So how to solve this asynchronous problem? Here are a few ways to solve it.
1.1.1 Using the useEffect helper
1.1.2 Passing the required data directly into the func method
1.1.3 Delayed triggering
A delayed trigger can also solve this problem, but this approach is least recommended. An asynchronous problem may create some other unknown problems if another asynchronous operation with a larger delay is used to underwrite it.
1.2 The state in setTimeout is always the initial value
We want to delay setting some data, for example to make a counter fixed simply by +1, we might write it like this:
However, when we run it, we find that the counter just goes from 0 to 1 and then never increases. When we log the callback function in setInterval, we find that the callback function is still executing, but the count is not changing.
This is due to the second parameter
dependency of useEffect. In our example above, the dependency is an empty array, which means that after the first initialization, the count never changes internally, so the count will always depend on the initial value at the beginning.
But how can we achieve continuous state manipulation in the timer? Here are a few solutions for you.
1.2.1 Adding a state to a dependency
As we said earlier, because of the dependencies, each read is the initial value. Then we can add
count to the dependency.
This will allow the counter to keep increasing.
But this leads to another problem: every time the count changes,
clearInterval is executed and then a new timer
setInterval is restarted, and setInterval becomes setTimeout, which will be cleaned up after only one setInterval. So here it’s actually setTimeout instead.
There is also a simpler and more brutal way of not adding any dependencies, but this way, it causes all state changes to trigger a re-execution of useEffect.
This approach, without any dependencies, is recommended for states with only one count in the component!
1.2.2 Using useRef to save the last state
We can use the useRef feature to save the value of the state that has just changed, so that the next time we use it, we can get it directly from useRef. useRef values are not constrained by dependencies.
2. The beauty of useRef
We’ve just tried out useRef for a little while. Now let’s see how it’s used.
2.1 Saving all variable values
useRef can hold all variable values, such as the values in the state above, as well as the timer of the timer, the id of the requestAnimationFrame, and so on. For example, in recursive operations, timer and id are different every time, so when canceling, it’s a headache to decide which one to cancel, so we can use useRef to store them.
2.2 Saving multiple variables at the same time
In the above examples, we have saved only one value and then overwritten it with another new value. But what if we want to save multiple values at the same time?
If it’s just data, then just initialize the ref to an array and operate as an array.
But we have a list of dom elements and we want to store all the dom elements?
Pay special attention here, the getDomList method should be wrapped in
useCallback, otherwise it will cause the domListRef data to increase every time the state changes!
2.3 Customizing the hook for useInterval
We learned about the performance of setTimeout(setInterval) and useRef in useEffect in Sections 1 and 2, and based on these two, we can implement a useTimeout or useInterval ourselves.
The useInterval implementation.
When you perform a set operation on a state in useInterval, you don’t have to worry about whether the state will be updated or not.
3. The magic of createPortal
When we introduce a component and render it, it will be rendered according to the position it was introduced. However, for some public components, such as popups, toast, hover pendants, etc., we don’t want the style of these components to be affected by the style of the parent element (e.g.
transform (if the parent element has transform style,
position: fixed will be downgraded to
z-index, etc.), it is better if she can render to the root directory or other specified directory. What should we do at this point?
createPortal, the rules of this method are very simple, just 2 parameters:
- the component to be rendered.
- the DOM node to be mounted.
The code explains the following.
<Modal /> component can be referenced anywhere and then rendered to the end of document.body when rendered (similar to the appendChild operation).
In fact, there are a lot of tips and tricks in react, so if we are familiar with them, we can quickly build our applications with react.