为何在条件语句中使用React Hooks未触发报错?
问题
根据React Hooks规则,我们不得在条件语句中使用任何Hooks。但下述示例代码却能正常运行,我不清楚为何未触发报错。
能否有人解释为何在if条件中使用Hooks却没有报错?
import { useEffect, useState } from "react"; let trackChanges = true; export default function Demo() { const [text1, setText1] = useState("First"); function onText1Change(value:string){ setText1(value); if (value.length > 8) { trackChanges = false; } else{ trackChanges = true; } } if (trackChanges){ useEffect(()=> { return () => { document.title=`${text1}`; } }, [text1]); } return ( <input onChange={e=>onText1Change(e.target.value)} value={text1}/> ) }
我在VS Code中编写这段代码,本以为会触发报错,但出乎意料的是它能正常运行,这与其他StackOverflow问题及React文档所述不符。只有当text1的值长度大于8时,才会在运行时崩溃。是不是我的lint设置有问题?为何未按照Hooks规则给出报错警告?
解答
一、为什么没触发lint报错?
Hooks的规则检查完全依赖eslint-plugin-react-hooks这个ESLint插件,如果你没安装或正确配置它,VS Code就不会自动检测到条件中使用Hooks的问题:
- 先检查项目
package.json的devDependencies里有没有eslint-plugin-react-hooks,没有的话需要手动安装 - 再看ESLint配置文件(比如
.eslintrc),要确保plugins数组包含react-hooks,同时开启react-hooks/rules-of-hooks和react-hooks/exhaustive-deps这两条规则
二、为什么初始能运行,长度超8才崩溃?
React是靠每次渲染时Hooks的调用顺序来跟踪状态的,这是Hook机制的核心要求:
- 初始状态下
trackChanges为true,组件渲染时会按顺序调用useState→useEffect,顺序固定,React能正常跟踪状态,所以没报错 - 当输入文本长度超过8,
trackChanges被设为false,下一次渲染时会跳过useEffect的调用,此时调用顺序变成只有useState,和之前的顺序不一致,直接破坏了React的状态跟踪逻辑,导致运行时崩溃 - 初始阶段只是“碰巧”没破坏顺序,属于错误用法下的侥幸运行,并非符合规则
三、正确的修复方式
不要在条件中包裹Hooks,把判断逻辑移到Hook内部,保证每次渲染时Hooks的调用顺序一致:
import { useEffect, useState } from "react"; export default function Demo() { const [text1, setText1] = useState("First"); const [trackChanges, setTrackChanges] = useState(true); function onText1Change(value:string){ setText1(value); setTrackChanges(value.length <= 8); } useEffect(()=>{ return () => { // 把条件判断移到Hook内部 if(trackChanges) { document.title=`${text1}`; } } }, [text1, trackChanges]); return ( <input onChange={e=>onText1Change(e.target.value)} value={text1}/> ) }
内容的提问来源于stack exchange,提问作者Sumanesh
相关产品推荐
相关产品推荐

