网站字体选择,永康网站建设服务,视频添加到wordpress,怎么开通自己的微信小程序为什么避免在循环、条件或嵌套函数中调用 Hooks 为了确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确。
我们可以在单个组件中使用多个 State Hook 或 Effect Hook#xff1a;
function Form… 为什么避免在循环、条件或嵌套函数中调用 Hooks 为了确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确。
我们可以在单个组件中使用多个 State Hook 或 Effect Hook
function Form() {// 1. 使用变量名为 name 的 stateconst [name, setName] useState(Mary);// 2. 使用 effect 以保存 form 操作useEffect(function persistForm() {localStorage.setItem(formData, name);});// 3. 使用变量名为 surname 的 stateconst [surname, setSurname] useState(Poppins);// 4. 使用 effect 以更新标题useEffect(function updateTitle() {document.title name surname;});// ...
}那么 React 怎么知道哪个 state 对应哪个 useState答案是 React 靠的是 Hook 调用的顺序。
let hookStates []; // 放着此组件的所有的hooks数据
let hookIndex 0; // 代表当前的hooks的索引
function useState(initialState){// 如果有老值取老值,没有取默认值hookStates[hookIndex] hookStates[hookIndex] || initialState;// 暂存索引let currentIndex hookIndex;//setState方法将当前值置为新值function setState(newState){hookStates[currentIndex] newState;//置完新值立刻触发渲染render();}return [hookStates[hookIndex], setState];
}因为我们的示例中Hook 的调用顺序在每次渲染中都是相同的所以它能够正常工作
// ------------
// 首次渲染
// ------------
useState(Mary) // 1. 使用 Mary 初始化变量名为 name 的 state
useEffect(persistForm) // 2. 添加 effect 以保存 form 操作
useState(Poppins) // 3. 使用 Poppins 初始化变量名为 surname 的 state
useEffect(updateTitle) // 4. 添加 effect 以更新标题// -------------
// 二次渲染
// useState - 不再使用传入的默认值而是返回上次渲染时存储的状态值。
// useEffect 首先运行之前 useEffect 的清理函数如果有的话然后再运行新的副作用函数。
// -------------
useState(Mary) // 1. 读取变量名为 name 的 stateMary参数被忽略
useEffect(persistForm) // 2. 清除并替换上一次 form 的 effect
useState(Poppins) // 3. 读取变量名为 surname 的 statePoppins参数被忽略
useEffect(updateTitle) // 4. 清除并替换上一次更新标题的 effect// ...useEffect Hook有什么作用如何理解 替换与清除
告诉 React 需要在完成DOM更新之后渲染之后执行一些“副作用”如数据获取、手动更改DOM、设置订阅或者清除上一次的副作用等。
useEffect(persistForm) 在首次渲染时添加了一个副作用即 persistForm 函数。然后在随后的组件更新第二次渲染中相同的 useEffect(persistForm) 调用会首先清除前一次的副作用如果 persistForm 返回了一个清除函数的话然后再执行新的 persistForm 副作用。
这样确保了副作用是最新的并且在多次渲染之间不会有冲突。这也是为什么我们说第二次和随后的渲染是“替换”前一次的副作用。
只要 Hook 的调用顺序在多次渲染之间保持一致React 就能正确地将内部 state 和对应的 Hook 进行关联。但如果我们将一个 Hook (例如 persistForm effect) 调用放到一个条件语句中会发生什么呢
比如
// ???? 在条件语句中使用 Hook 违反第一条规则if (name ! ) {useEffect(function persistForm() {localStorage.setItem(formData, name);});}在第一次渲染中 name ! ‘’ 这个条件值为 true所以我们会执行这个 Hook。但是下一次渲染时我们可能清空了 name表达式值变为 false。此时的渲染会跳过该 HookHook 的调用顺序发生了改变
useState(Mary) // 1. 读取变量名为 name 的 state参数被忽略
// useEffect(persistForm) // ???? 此 Hook 被忽略
useState(Poppins) // ???? 2之前为 3。读取变量名为 surname 的 state 失败
useEffect(updateTitle) // ???? 3 之前为 4。替换更新标题的 effect 失败第一次调用 useState(Mary)此时 hookIndex0状态被存储在 hookStates[0]。 然后我们跳过 useEffect(persistForm)。 接下来的 useState(Poppins) 会使用 hookIndex1但在上一次渲染中它使用了 hookIndex2。这会导致 surname 的状态从错误的位置获取。 以此类推后续的 useEffect(updateTitle) 也会使用错误的索引。