1、前言
前几节我们实现了React基本功能,本节我们来添加React16.8的核心功能hooks。
编写一个计数器的功能;
// src/indeximport React from '../react'function Counter() {const [state, setState] = React.useState(1)return (<div><h1 >Count: {state}</h1><button onClick={() => setState(c => c + 1)}>+1</button></div>)}const element = <Counter />React.render(element, document.getElementById("root"))
2、实现步骤
2.1 添加useState函数
// react/react-dom.jsfunction useState(initial){// todo}
2.2 初始化全局变量
我们知道函数每重新调用一次,内部状态就会丢失,所以我们需要一个记录内部内部状态的变量;
设置正在工作的fiber和添加一个数组来记录多次调用useState,使用索引来追踪;
let wipFiber = nulllet hookIndex = null/*** 函数组件处理* @param {*} fiber*/function updateFunctionComponent(fiber) {wipFiber = fiberhookIndex = 0wipFiber.hooks = []// 省略}
2.3 添加useState函数的state
/*** @param {*} initial 传进来的初始值* @returns*/function useState(initial) {// 检查是否有旧的hooksconst oldHook =wipFiber.alternate &&wipFiber.alternate.hooks &&wipFiber.alternate.hooks[hookIndex]// 如果有旧的,就复制到新的,如果没有初始化const hook = {state: oldHook ? oldHook.state : initial,}wipFiber.hooks.push(hook)hookIndex++return [hook.state]}
2.4 添加useState函数的setState
设置一个新的正在进行的工作根作为下一个工作单元,这样工作循环就可以开始一个新的渲染阶段;
// 设置hooks状态const setState = action => {debuggerhook.queue.push(action)// 设置一个新的正在进行的工作根作为下一个工作单元,这样工作循环就可以开始一个新的渲染阶段wipRoot = {dom: currentRoot.dom,props: currentRoot.props,alternate: currentRoot,}nextUnitOfWork = wipRootdeletions = []}
2.5 更新状态
function useState(initial) {// 省略const actions = oldHook ? oldHook.queue : []actions.forEach(action => {hook.state = typeof action === 'function' ? action(hook.state) : action})// 省略}
3、运行结果
把useState函数结果导出;

运行结果:
