In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the relevant knowledge of "what are the knowledge points about useState". In the operation of actual cases, many people will encounter such a dilemma. Next, let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
How hook saves data
FunctionComponent's render itself is just a function call.
So how does the hook called inside render get the corresponding data?
For example:
UseState gets state
UseRef gets ref
UseMemo acquires cached data
The answer is:
Each component has a corresponding fiber node (which can be understood as a virtual DOM), which is used to hold information about the component.
Each time you FunctionComponent render, the global variable currentlyRenderingFiber is assigned to the fiber node corresponding to that FunctionComponent.
So, inside hook, you actually get status information from currentlyRenderingFiber.
How to get data from multiple hook
We know that there may be multiple hook in a FunctionComponent, such as:
Function App () {/ / hookA const [a, updateA] = useState (0); / / hookB const [b, updateB] = useState (0); / / hookC const ref = useRef (0); return
;}
So how do multiple hook get their own data?
The answer is:
An one-way linked list of data corresponding to hook is kept in currentlyRenderingFiber.memoizedState.
For the example above, it can be understood as:
Const hookA = {/ / hook saved data memoizedState: null, / / points to the next hook next: hookB / /. Omit other fields}; hookB.next = hookC; currentlyRenderingFiber.memoizedState = hookA
When FunctionComponent render, each time a hook is executed, the pointer to the currentlyRenderingFiber.memoizedState linked list is moved backwards to the current hook corresponding data.
This is why React requires that the order of hook calls cannot be changed (hook cannot be used in conditional statements)-each time render is fetched from a fixed-order linked list.
UseState execution process
We know that the second parameter of the useState return value array is the method that changes the state.
In the source code, he is called dispatchAction.
Whenever dispatchAction is called, an object update representing an update is created:
Const update = {/ / updated data action: action, / / points to the next update next: null}
For the following example
Function App () {const [num, updateNum] = useState (0); function increment () {updateNum (num + 1);} return {num}
;}
Calling updateNum (num + 1) creates:
Const update = {/ / updated data action: 1, / / points to the next update next: null / /. Omit other fields}
If you call dispatchAction multiple times, for example:
Function increment () {/ / generate update1 updateNum (num + 1); / generate update2 updateNum (num + 2); / / generate update3 updateNum (num + 3);}
Then the update forms a circular linked list.
Update3-- next-- > update1 ^ | | update2 | _ next_ |
Where can I keep this linked list?
Since the update linked list is generated by the dispatchAction of a useState, the linked list clearly belongs to that useState hook.
We continue to supplement the data structure of hook.
Const hook = {/ / hook saved data memoizedState: null, / / points to the next hook next: hookForB / / this update calculates the new state baseState: null based on baseState, / / the update queue that already existed at the beginning of this update baseQueue: null, / / the update queue to be added for this update queue: null,}
Among them, the linked list of the updated update is saved in queue.
When calculating state, the circular linked list of queue is cut and mounted at the end of baseQueue, and baseQueue calculates the new state based on baseState.
After calculating the state, the new state becomes memoizedState.
The reason why updates are not based on memoizedState but on baseState is that priority needs to be considered in the calculation process of state, and some update priorities may not be skipped. So memoizedState is not necessarily the same as baseState. For a more detailed explanation, see the revelation of React Technology [1]
Let's go back to our first question at the beginning:
Function App () {const [num, updateNum] = useState (0); window.updateNum = updateNum; return num;}
Can the 0 in the view be updated to 1 by calling window.updateNum (1)?
We need to look at the concrete implementation of the updateNum method here:
UpdateNum = = dispatchAction.bind (null, currentlyRenderingFiber, queue)
As you can see, the updateNum method binds the dispatchAction of currentlyRenderingFiber and queue (that is, hook.queue).
As mentioned earlier, the purpose of calling dispatchAction is to generate update and insert it into the hook.queue linked list.
Now that queue has been bound to dispatchAction as a preset parameter, calling dispatchAction is limited to FunctionComponent.
Action of update
The second question
Function App () {const [num, updateNum] = useState (0); function increment () {setTimeout (()) = > {updateNum (num + 1);}, 1000);} return {num}
;}
Quickly click p5 times in 1 second, how many times does it show on the view?
We know that calling updateNum produces update, where passing parameters becomes update.action.
Click 5 times in 1 second. At the fifth click, the update created by the first click has not yet entered the update process, so the hook.baseState has not changed.
Then the update generated by these five clicks is based on the same baseState to calculate the new state, and the num variable has not changed (that is, five times update.action (that is, num + 1) is the same value).
Therefore, the final rendering result is 1.
UseState and useReducer
So, how do you gradually change the view from 1 to 5 with 5 clicks?
From the above knowledge, we know that we need to change baseState or action.
BaseState is determined by the update process of React, and we can't control it.
But we can control action.
Action can pass not only values but also functions.
/ / action is the value updateNum (num + 1); / / action is the function updateNum (num = > num + 1)
In the process of generating a new state based on baseState and update linked lists:
Let newState = baseState; let firstUpdate = hook.baseQueue.next; let update = firstUpdate; / / traverses every update do {if (typeof update.action = 'function') {newState = update.action (newState) in baseQueue;} else {newState = action;}} while (update! = = firstUpdate)
It can be seen that when passing a value, since our action is the same value five times, the final calculated newState is also the same value.
In the case of transfer function, newState calculates 5 times based on action function, and finally gets the cumulative result.
If we use useReducer instead of useState in this example, since the action of useReducer is always a function, we won't encounter the problem in our example.
In fact, useState itself is a useReducer with the following reducer preset.
Function basicStateReducer (state, action) {return typeof action = = 'function'? Action (state): action;} what are the knowledge points about useState? that's all. Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.