React严格模式下useEffect清理函数提前执行的原因及解决方案
React严格模式下表单初始化值被提前清空的问题解决
问题原因
React严格模式在开发环境中会触发组件的「挂载-卸载-重新挂载」流程,用于检测组件副作用是否符合规范。你的子组件中,空依赖的useEffect清理函数会在第一次挂载后的假卸载阶段执行,直接调用props.setInitialValues({})清空父组件状态。当组件重新挂载时,子组件拿到的props.initialValues已经是空对象,导致新增/编辑的判断逻辑失效。
解决办法
方案一:区分严格模式的假卸载与真实卸载
通过标志位和延迟执行,确保只有组件真实卸载时才清空状态:
import { useRef } from "react"; const DivisionMasterForm: FunctionComponent<DivisionMasterFormProps> = (props) => { const isRealUnmount = useRef(false); useEffect(() => { return () => { isRealUnmount.current = true; // 延迟执行,让React完成严格模式的重新挂载判断 setTimeout(() => { if (isRealUnmount.current) { props.setInitialValues({}); } }, 0); }; }, []); // 重新挂载时重置标志 useEffect(() => { isRealUnmount.current = false; }, []); // ... 其余代码不变 };
方案二:将状态清理逻辑移至父组件(推荐)
遵循「状态拥有者管理状态」的原则,由父组件控制表单显示/隐藏时的状态清理:
// 父组件代码 const [showForm, setShowForm] = useState(false); const [initialValues, setInitialValues] = useState<IDivisionMaster>({}); // 当表单关闭时清空初始化值 useEffect(() => { if (!showForm) { setInitialValues({}); } }, [showForm]); // 编辑场景:设置初始化值并显示表单 const handleEdit = (data: IDivisionMaster) => { setInitialValues(data); setShowForm(true); }; // 新增场景:清空初始化值并显示表单 const handleAdd = () => { setInitialValues({}); setShowForm(true); };
子组件中移除清空状态的useEffect,专注于表单渲染与提交逻辑即可。
方案三:保留初始化时的ID判断
如果只需要基于表单初始化时的状态判断新增/编辑,可以将初始化时的id存入ref,避免后续props变化影响判断:
const DivisionMasterForm: FunctionComponent<DivisionMasterFormProps> = (props) => { // 保存初始化时的id const initialId = useRef(props.initialValues.id); const onSubmit: SubmitHandler<IDivisionMaster> = (val) => { if (initialId.current) { console.log("update"); } else { dispatch(addDivisionMaster(val)); } }; // ... 其余代码不变,移除清空状态的useEffect };
内容的提问来源于stack exchange,提问作者santhosh
相关产品推荐
相关产品推荐

