随着 react-hook 正式发布,大家一夜之间都爱上了这个小家伙。useState, useEffect, useMemo ... 大家体验了它们的姿势之后,都深表喜欢。极大的减少了组件的代码量,让组件看起来干净整洁。但使用时想必大家都出现了疑惑为什么这些函数要按顺序写。比如以下代码是不被允许的。
let value = true;
const App = (props) => {
if(value) {
const [v,setV] = useState('v');
}else {
const [t,setT] = useState('t');
}
return <div>这是不被允许的</div>;
};
接下来我就通过编写一个阉割版 useState 函数的方法来为大家解答这个问题。
首先我们编写一个简单的渲染函数,一旦调用这个函数组件进行重渲染。( 这只是使用了最简单粗暴的方法进行重渲染,真实的渲染环境较为复杂), stateIndex
会在下文讲解。
const reRender = () => {
stateIndex = -1
ReactDOM.render(<App/>,document.getElementById('root'))
}
下面我们在来简单实现一下 useState 。
let stateQueue = []; // 用于存放每个useState返回值。
let stateIndex = -1; //给每个 useState的返回值一个序号。
function useState(initState) {
stateIndex++;
stateQueue[stateIndex] = stateQueue[stateIndex] || initState;
const currentIndex = stateIndex
function setState(newState) {
stateQueue[currentIndex] = newState;
reRender(); //组件重渲染
}
return [stateQueue[stateIndex],setState]
}
从这可以看出每次调用一次 useState
, stateQueue 就会存储一个值,比如你在App组件中使用 [v,setV] = useState('v')
,那么 stateQueue[0]
的值会变为 'v'
,其次stateIndex会加1。 再次调用 [t, setT] = useState('t')
,stateQueue[1]
的值会是't'
,以此类推。
在看看 setState , 假如你在此时调用setV('v1')
,那么由于闭包
的原因将会执行stateQueue[0] = 'v1'
,从而改变 stateQueue[0]
的值,接下来也是最关键的一步,reRender 被调用,stateIndex
重新变为-1,App组件重渲染, [v,setV] = useState('v')
将会再次被调用,但此时将会调用stateQueue[0] || iniState
而他现在的返回值为 'v1'
, 变量 v 的值也就会等于 v1 渲染在页面上。这也就是 useState 的大致处理过程。
此时在来回答最开始的问题, 为什么最开始的那个案例是不被允许的。想象一下假如最开始那个 value
的值是 true,那么他会让
变量 v = stateQueue[0] = 'v' , 此时再调用 setV('v1')
,页面重渲染,如果此时 value
的值是 false, 那么他会让
变量 t = stateQueue[0] = 'v1' ,这显然不是我们想看见的。所以 react-hook 为了杜绝这种事情发生,不允许 hook 函数在 if 语句中使用。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!