ReactJS中file类型输入出现受控转非受控错误的原因咨询
问题场景
我在ReactJS中使用file类型输入框获取用户图片文件,相关代码如下:
State定义
const [frSignUpData, setFrSignUpData] = useState({ name: '', email: '', img: '', })
文件输入框代码
<label htmlFor="img">Upload a photo :</label> <input id="img" name="img" type='file' onChange={handleChange} accept="image/*" multiple={false} />
onChange处理函数
function handleChange(e) { if(e.target.name == 'img'){ setFrSignUpData(prevData => ({ ...prevData, [e.target.name]: e.target.files[0] })) } }
组件渲染后控制台报错:
A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component
将输入框拆分为独立组件并传递setFrSignUpData作为props后错误消失,但我想了解该错误的产生原因。注:我了解file类型输入框是不受控的,无需传递value属性。
错误原因拆解
React的隐式受控判断逻辑冲突
你虽然没给file输入框显式写value属性,但整个表单的其他输入(name、email)都是受控状态,且和file输入框共享同一个frSignUpDatastate对象。React会自动扫描表单关联的state字段,发现img在state中存在,就默认把这个file输入框当成受控组件处理。但file输入框天生是非受控组件,无法通过value属性控制,这种逻辑矛盾直接触发了错误。state值的类型突变打乱状态追踪
初始state里img是空字符串''(明确的字符串类型值),选完文件后你把它改成了File对象。React对受控输入的要求是值的类型必须稳定,不能从字符串突然跳转为对象。这种类型突变让React误以为你把一个受控输入改成了非受控,因此抛出了报错信息。拆分组件的修复逻辑
把file输入框拆成独立组件后,它和父组件的frSignUpData不再是直接绑定的关系。子组件只负责调用父组件传入的setFrSignUpData更新状态,自身作为独立的非受控输入存在,React不会再把它和父组件的其他受控输入混为一谈,自然就避免了状态推断的冲突。
内容的提问来源于stack exchange,提问作者Sumit

