状态更新后React ref持续为undefined的问题求助
问题分析与解决方案
问题根源
- Ref创建方式错误:使用
React.createRef()会在组件每次重渲染时生成新的引用对象。调用setError触发重渲染后,新的ref被创建,但之前传给validator的验证函数捕获的是旧的ref实例,旧ref的current会和原输入元素解绑,导致后续调用时current为undefined。 - 验证函数重复注册:每次组件渲染都会调用
validator()传入新的验证函数,外部按钮触发的可能是旧的验证函数,而旧函数捕获的是已失效的ref。
修正后的代码
import { StepData } from "@/components/steptree/StepData"; import { Input } from "@material-tailwind/react"; import { RegisterValidateHandler } from "./DataHandler"; import React, { useRef, useCallback, useEffect } from "react"; export function StartDataHandler({ stepData, validator } : {stepData: StepData, validator : RegisterValidateHandler}) { const [error, setError] = React.useState(""); // 用useRef替代React.createRef,保证组件生命周期内引用唯一 const testInputRef = useRef<HTMLInputElement>(null); // 用useCallback包裹验证函数,确保依赖变化时才更新 const validate = useCallback(() => { console.log("testInputRef value: ", testInputRef.current?.value); if (testInputRef.current?.value === "test") { // 验证通过时清空错误信息 setError(""); return true; } else { setError("输入值必须为'test'"); return false; } }, [testInputRef, setError]); // 用useEffect注册验证函数,仅在组件挂载或validate变化时执行一次 useEffect(() => { validator(validate); }, [validator, validate]); return ( <div> {error && <h2>{error}</h2>} <input ref={testInputRef} type="text" placeholder="test start"/> {/* <Input ref={testInputRef} label="test start"/> */} </div> ) }
关键修改说明
useRef替代React.createRef:useRef会在组件整个生命周期内保持同一个引用对象,无论组件重渲染多少次,ref的current始终指向同一个输入元素。useCallback包裹验证函数:确保只有当依赖(testInputRef、setError)变化时,才生成新的验证函数,避免不必要的重复注册。useEffect注册验证函数:控制验证函数的注册时机,仅在组件初始化或验证函数更新时注册一次,避免每次渲染都向validator传入新函数,保证外部调用的是最新的验证逻辑。
内容的提问来源于stack exchange,提问作者Colin Degen
相关产品推荐
相关产品推荐

