源码:

    1. // 为了可以储存多个值
    2. let state = [];
    3. // 存储改变值的方法
    4. let setters = [];
    5. // 根据这个下标查找对应的值和改变值的方法
    6. let stateIndex = 0;
    7. // 函数主体
    8. function useState(initialState) {
    9. // 1. 因为useState可以调用多次,单独一个变量无法存储多个值,所以使用数组进行存储
    10. /*
    11. * 每次改变值都会重新渲染,每次渲染都会重新调用useState方法,
    12. * 这个判断是为了组件渲染前是否有存储过值,如果有就取出来,如果没有就取初始传递的值
    13. */
    14. state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialState;
    15. // 2. 将改变值的方法存储到数组中
    16. setters.push(createSetter(stateIndex))
    17. // 3. 根据下标在存储值的数组查出值,根据下标在存储改变方法的数组查出方法
    18. let value = state[stateIndex]
    19. let setter = setters[stateIndex]
    20. // 4. useState是将值和改变值的方法存储到数组中,所以在组件中每次使用useState方法,就会将值和方法存起来,每次存起来存储的数组下标就会+1
    21. stateIndex++;
    22. // 5. useState方法最终返回一个数组,数组有两个参数,一个是值,一个是改变值的方法
    23. return [value, setter]
    24. }
    25. /*
    26. 这里解释一下为什么要以闭包的形式将改变值的方法存储到数组中;
    27. 闭包有个特性就是当前代码执行完毕,闭包中的参数不会被垃圾回收机制所回收
    28. 所以我们通过闭包这种形式将下标存储到闭包中;
    29. setters存储改变值的方法,当我们在组件中想要改变值的时候,只需要将新值传到方法中,
    30. 也就是createSetter返回的方法,createSetter这个方法将新值,根据之前闭包保存下来的下标,
    31. 去更新state中对应的值;
    32. */
    33. function createSetter(index) {
    34. return function (newState) {
    35. state[index] = newState;
    36. render()
    37. }
    38. }
    39. // 这里的render方法用于重新渲染组件
    40. function render(){
    41. // 这里将stateIndex重置为0,是为了每次重新渲染下标都要从0开始
    42. // 如果不清0,那么下标就会一直增加下去,就会出现问题
    43. stateIndex = 0
    44. effectIndex = 0
    45. ReactDOM.render(<StateYM/>, document.getElementById('root'))
    46. }