跳到主要内容

使用 Hooks 的重要规范

再次强调命名规范 useXxx

Hooks 使用规范

  • 只能用于 React 函数组件和自定义 Hook 中,其他地方不可以
  • 只能用于顶层代码,不能在循环,判断中使用 Hooks
  • eslint 插件 eslint-plugin-react-hooks 可以帮到你

错误例子


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 配置

// 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 严重依赖于调用顺序!特别重要

例子

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

测试代码

<TeachDemo couseName={'前端课程'}></TeachDemo>