04.useState源码实现
代码演化过程见视频,这里只呈现相关代码:
hooks.js
js
import {emitUpdateForHooks } from './react-dom'
let states = [];
let hookIndex = 0
export function resetHookIndex(){
hookIndex = 0
}
export function useState(initialValue) {
states[hookIndex] = states[hookIndex] || initialValue;
const currentIndex = hookIndex;
function setState(newState) {
states[currentIndex] = newState;
emitUpdateForHooks();
}
return [states[hookIndex++], setState];
}react-dom.js
js
import { resetHookIndex } from './hooks'
export let emitUpdateForHooks;
let isHooksUpdated = false
function render(VNode, containerDOM){
// ...
emitUpdateForHooks = () => {
if (!isHooksUpdated) {
isHooksUpdated = true;
queueMicrotask(() => {
isHooksUpdated = false;
resetHookIndex()
updateDomTree(VNode, VNode, findDomByVNode(VNode));
})
}
}
}
function getDomByFunctionComponent(VNode){
let { type, props} = VNode
let renderVNode = type(props)
if(!renderVNode) return null
VNode.oldRenderVNode = renderVNode /////
let dom = createDOM(renderVNode)
VNode.dom = dom
return dom
}
function mountArray(children, parent){
if(!Array.isArray(children)) return
for(let i = 0; i < children.length; i++){
if(!children[i]) {///
children.splice(i, 1)///
i--///
continue///
}////
children[i].index = i;
mount(children[i], parent)
}
}
function updateChildren(parentDOM, oldVNodeChildren, newVNodeChildren) {
//...
newVNodeChildren.forEach((newVNode, index) => {
newVNode.index = index
let newKey = newVNode.key ? newVNode.key : index;
let oldVNode = oldKeyChildMap[newKey];
if (oldVNode) {
////////////////////
updateDomTree(oldVNode, newVNode, findDomByVNode(oldVNode));/////
// ....
}
// ...
});react.js
js
export * from './hooks' ////