React传递父状态重置自定义文件输入子组件时状态不更新如何解决
问题根因
你犯了React开发中的典型错误:将组件实例存储在了父组件的state中。
你第一次调用returningInputs生成CustomInput组件数组并存入filesInputs状态时,组件绑定的reset prop是当时的resetInputs初始值false。后续你更新resetInputs状态时,已经存在state中的旧组件实例不会自动更新prop,因此子组件收不到最新的reset值,关联的useEffect自然不会触发。
另外还有三个隐藏问题:
- 重置逻辑不闭环:
resetInputs设为true后没有复位逻辑,后续第二次重置会因为依赖值无变化无法触发useEffect - 原生文件输入框未清空:仅重置React状态不会清空原生
<input type="file">中存储的文件,后续用户选择同一个文件时不会触发onChange事件 - 禁用属性逻辑错误:
disabled={disabler && !disabler}的运算结果永远为false,无法实现禁用效果
修复方案
- 删除组件存储逻辑,渲染时动态生成子组件
删掉父组件中returningInputs、setFilesInputs相关代码,直接在父组件render阶段循环生成CustomInput,确保每次渲染都能传入最新的prop值:
// 父组件return中直接写如下代码,替换原来的{filesInputs} { Array.from({length: filesCounter}).map((_, i) => ( <CustomInput key={`custom input ${i}`} setUpperLevelFile={handlingInputChange} lastInput={i === filesCounter - 1} reset={resetInputs} /> )) }
- 补全重置状态的复位逻辑
在父组件中新增useEffect,重置完成后自动把resetInputs改回false,保证后续可以重复触发重置:
// 父组件新增 useEffect(() => { if(resetInputs) { setResetInputs(false); } }, [resetInputs])
- 子组件新增原生输入框清空逻辑
给子组件的文件输入框加ref,重置时同步清空原生输入框的值,同时修复禁用属性的逻辑错误:
// 子组件新增ref const inputRef = useRef(null); // 调整reset的useEffect useEffect(() => { if (reset) { setFileUpload(null); inputRef.current.value = ''; // 清空原生文件输入框存储的文件 } console.log("custom input use effect : ", reset); }, [reset]); // input标签调整如下 <input type="file" name="realInput" className="innerFileInput" accept={typeOfFiles ?? ''} disabled={!!disabler} // 修复禁用逻辑 ref={inputRef} // 绑定ref style={{ display: "none" }} onChange={(e) => { setFileUpload(e.target.files[0]); }} />
内容的提问来源于stack exchange,提问作者FlowRan
相关产品推荐
相关产品推荐

