对于react 的 useState你真的理解对了吗?

390 阅读2分钟

前言: 为什么要写这篇文章, 在我自己学习react hooks 的时候, 对于setState的理解并不是很升入, 在开发一年多后, 偶然看到一个机构讲解useState 的时候, 颠覆了我对useState 的认认识, 浮现出的想法是我学的有问题还是别人讲的有问题, 于是有了这篇文章

  • 先来看看react useState 的用法
const [m, setM] = useState(0);

return (
    <div>
        <div>m: {m}</div>
        <button onClick={() => setM(m+1)}>+1</button>
    </div>
)

问题: 点击onClick 事件时候 setM() 方法修改的是m 还是新的值用来替换m , 然后自己实现一个来弄清楚

  • 现在来实现一个简单的 useState
    function App() {
    
        function myUseState(inintValue) {
           let upDateValue = inintValue;
           
           function setValue(newValue) {
               upDateValue = newValue;
           }
        
           return [upDateValue, setValue];
        }
    }

上面的代码会有一个问题每次执行 myUseState 方法 upDateValue 的value 都是默认值, 所以改进一下

    let _state;
    const render = () => ReactDOM.render(<App />, document.getElementById(('root')))
    function App() {
    
        function myUseState(inintValue) {
           _state = _state === undefined ? inintValue : _state;
           
           function setValue(newValue) {
               _state = newValue;
               render();
           }
        
           return [upDateValue, setValue];
        }
    }
  • 到这里一个简单的 useState 已经实现完成 下面看运行结果

WechatIMG21.png

这里是初始化 的值, 下面点击看运行

WechatIMG22.png

ps : 这样的写法 对于多个useState 肯定会有问, 在改进一下

    let _state = [];
    let index = 0;
    const render = () =>  ReactDOM.render(<App />, document.getElementById(('root')))
    function App() {
        function myUseSTate(initValue) {
            const currentIndex = index;
            index += 1;
            
            _state[currentIndex] = _state[currentIndex] || initValue;
            
            function setValue(newValue) {
                _state[currentIndex] = newValue;
                render();
            }
            return [_state[currentIndex], setValue];
        }
    }

代码写到这里会有一个问题, 执行setValue value的值改了, 但是页面并没有更新, 实际的原因是因为执行 setValue 之后, 需要重置index , 那就在改进一下

    let _state = [];
    let index = 0;
    const render = () =>  ReactDOM.render(<App />, document.getElementById(('root')))
    function App() {
        function myUseSTate(initValue) {
            const currentIndex = index;
            index += 1;
            
            _state[currentIndex] = _state[currentIndex] || initValue;
            
            function setValue(newValue) {
                _state[currentIndex] = newValue;
                render();
                index = 0;
            }
            return [_state[currentIndex], setValue];
        }
    }

到这里基本实现完成, 为什么在这里要用数组 而不是对象, 简单点来说, react useState 的用法是 const [n, setN] = useState(0) ,而不是 const [n, setN] = useState('n1', 0), 也说明了为什么 hooks 为什么不能出现在条件语句里面

最后: 其实在react 内部真正的index对应的是fiber 对象上的一个属性,根据这个属性知道当前的useState 顺序, 目前正在学习fiber, 学习完成之后在更新 fiber 是怎么实现hooks的 ,谢谢观看