使用 Hooks 的重要规范
再次强调命名规范 useXxx
Hooks 使用规范
- 只能用于 React 函数组件和自定义 Hook 中,其他地方不可以
- 只能用于顶层代码,不能在循环,判断中使用 Hooks
- eslint 插件 eslint-plugin-react-hooks 可以帮到你
错误例子
js
function Demo() {
const [count, setCount] = useState(0);
// 错误例子
if (count) {
useEffect(() => {
console.log('count', count);
});
}
// 错误例子
for (let i = 0; i < 100; i++) {
const [age, setAge] = useState(0);
}
// 错误例子
if (!count) {
return;
}
//....
}
eslint-plugin-react-hooks 配置
json
// ESLint 配置
{
"plugins": [
// ...
"react-hooks"
],
"rules": {
// ...
"react-hooks/rules-of-hooks": "error", // 检查 Hook 的规则
"react-hooks/exhaustive-deps": "warn" // 检查 effect 的依赖
}
}
Hooks 的调用顺序
Hooks 调用顺序必须保持一致
- 无论是 render 还是 re-render,Hooks 调用顺序必须一致
- 如果 Hooks 出现在循环,判断里,则无法保证顺序一致
- Hooks 严重依赖于调用顺序!特别重要
例子
js
import React, { useEffect, useState } from 'react';
function TeachDemo({ couseName }) {
// 函数组件,纯函数,执行完即销毁
// 所以,无论组件初始化(render)还是组件更新(re-render)
// 都会重新执行一次这个函数,获取最新的组件
// 这一点和 class 组件不一样
// render: 初始化 state 的值 '张三'
// re-render: 读取 state 的值 '张三'
const [studentName, setStudentName] = useState('张三');
// 错误代码================
// if(couseName){
// const [studentName, setStudentName] = useState('张三')
// }
// 错误代码 end================
// render: 初始化 state 的值 'lzw'
// re-render: 读取 state 的值 'lzw'
const [teacherName, setTeacherName] = useState('lzw');
// 错误代码================
// if(couseName){
// const [studentName, setStudentName] = useState('张三')
// const [teacherName, setTeacherName] = useState('lzw')
// }
// if(couseName){
// useEffect(() => {
// // 模拟学生签到
// localStorage.setItem('name', studentName)
// })
// }
// 错误代码 end================
// render: 添加 effect 函数
// re-render: 替换 effect 函数(内部的函数也会重新定义)
useEffect(() => {
// 模拟学生签到
localStorage.setItem('name', studentName);
});
// render: 添加 effect 函数
// re-render: 替换 effect 函数(内部的函数也会重新定义)
useEffect(() => {
// 开始上课
console.log(`${teacherName} 开始上课,学生 ${studentName}`);
});
return (
<div>
课程:{couseName}, 讲师:{teacherName}, 学生:{studentName}
</div>
);
}
export default TeachDemo;
测试代码
js
<TeachDemo couseName={'前端课程'}></TeachDemo>