Hook规则
Hook 本质就是 JavaScript 函数,但是在使用它时需要遵循两条规则。并且React要求强制执行这两条规则,不然就会出现异常的bug
- 只在最顶层使用 Hook
不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层调用他们
- 只在 React 函数中调用 Hook
不要在普通的 JavaScript 函数中调用 Hook,这两条规则出现的原因是,我们可以在单个组件中使用多个State Hook 或 Effect Hook,React 靠的是 Hook 调用的顺序来知道哪个 state 对应哪个useState
function Form() {
const [name1, setName1] = useState('Arzh1');
const [name2, setName2] = useState('Arzh2');
const [name3, setName3] = useState('Arzh3');
// ...
}
// ------------
// 首次渲染
// ------------
useState('Arzh1') // 1. 使用 'Arzh1' 初始化变量名为 name1 的 state
useState('Arzh2') // 2. 使用 'Arzh2' 初始化变量名为 name2 的 state
useEffect('Arzh3') // 3. 使用 'Arzh3' 初始化变量名为 name3 的 state
// -------------
// 二次渲染
// -------------
useState('Arzh1') // 1. 读取变量名为 name1 的 state(参数被忽略)
useState('Arzh2') // 2. 读取变量名为 name2 的 state(参数被忽略)
useEffect('Arzh3') // 3. 读取变量名为 name3 的 state(参数被忽略)
如果我们违反React的规则,使用条件渲染
if (name !== '') {
const [name2, setName2] = useState('Arzh2');
}
假设第一次(name !== '')为true的时候,执行此Hook,第二次渲染(name !== '')为false时,不执行此Hook,那么Hook的调用顺序就会发生变化,产生bug
useState('Arzh1') // 1. 读取变量名为 name1 的 state
//useState('Arzh2') // 2. Hook被忽略
useEffect('Arzh3') // 3. 读取变量名为 name2(之前为name3) 的 state
React 不知道第二个 useState 的 Hook 应该返回什么。React 会以为在该组件中第二个 Hook 的调用像上次的渲染一样,对应的是 arzh2 的 useState,但并非如此。所以这就是为什么React强制要求Hook使用必须遵循这两个规则,同时我们可以使用 eslint-plugin-React-Hooks来强制约束