关于在useRef变量或JavaScript变量(如let)中使用useState的可行性及特定写法的技术咨询
关于在useRef/普通变量中使用useState的常见疑问解答
嘿,这两个问题问到点子上了,都是新手刚接触React Hooks时容易踩的坑!我来给你掰扯清楚:
1. 能否在useRef变量或let这类JavaScript变量中使用useState?
绝对不行!React的Hooks有一套严格的调用规则:所有Hook(包括useState)必须在函数组件的顶层作用域直接调用,不能嵌套在任何条件语句、循环、普通函数、对象属性赋值,或者像useRef的初始值、let变量赋值这类场景里。
为啥管这么严?因为React是靠Hook的调用顺序来精准追踪每个状态的。要是你在非顶层的地方调用useState,React就没法保证每次组件渲染时Hook的调用顺序一致,轻则出现状态不更新、渲染异常,重则直接抛出Invalid hook call这类错误,让你的组件彻底罢工。
2. 能否采用你举例的三种方式使用useState?
这三种写法全都是违反Hook规则的,绝对不能这么用!咱们一个个拆解:
const testRef = useRef({ test: useState("11") });:这里useState是作为useRef初始值对象的属性值调用的,相当于把Hook嵌套在了另一个Hook的参数里,完全不符合“顶层调用”的要求。const testObj = { test: useState("HI") };:直接在普通对象的属性里调用useState,同样不在组件顶层,React根本没法正确追踪这个Hook的调用顺序。let testRef = useRef(useState("HI"));:和第一个例子同理,useState作为useRef的初始参数被调用,不是在组件顶层直接执行,妥妥违反规则。
如果你的需求是想用ref保存状态相关的内容,正确的姿势应该是先在组件顶层调用useState拿到状态和更新函数,再把它们放到ref里,比如:
// 先在顶层调用useState const [testState, setTestState] = useState("11"); // 再把状态和更新函数存入ref const testRef = useRef({ test: [testState, setTestState] }); // 如果需要让ref实时同步最新状态,可以加个useEffect useEffect(() => { testRef.current.test[0] = testState; }, [testState]);
这样既遵守了Hook规则,又能实现你想要的效果~
内容的提问来源于stack exchange,提问作者YFI MM
相关产品推荐
相关产品推荐

