警告:组件正在更改类型文件的受控输入
Warning: A component is changing a controlled input of type file
在一个使用 React 的应用程序中,我有一个 form
和 radio
输入,它选择要呈现的组件,但是当我更改单选选项时,会显示此警告 -
“组件正在将类型文件的不受控输入更改为受控。输入元素不应从不受控切换为受控(反之亦然)。在组件的生命周期内决定使用受控或不受控输入元素“
表格
import React, { useState } from "react";
export default () => {
const [link, setLink] = useState("");
const [arquivo, setArquivo] = useState("");
const [forma_envio, setFormaEnvio] = useState("");
return(
<React.Fragment>
<div className="form-check ">
<input
type="radio"
className="form-check-input"
name="forma"
id="forma1"
value="File"
checked={forma_envio === "File"}
onChange={(e) => {
setFormaEnvio(e.target.value);
}}
/>
</div>
<div className="form-check ">
<input
type="radio"
className="form-check-input"
name="forma"
id="forma2"
value="Link"
checked={forma_envio === "Link"}
onChange={(e) => {
setFormaEnvio(e.target.value);
}}
/>
</div>
{forma_envio === "File" ? (
<input
type="file"
className="form-control-file form-control"
id="arquivo"`
onChange={(e) => {
e.preventDefault();
handleUpload(e.target.files[0]);
}}
/>
) :forma_envio === "Link" (
<input
value={link}
type="text"
className="form-control"
id="link"
onChange={(e) => {
e.preventDefault();
setLink(e.target.value);
}}
/>
):
("")}
</React.Fragment>
);
}
所有州都以 ""
开头。
一切正常,但我仍然不知道如何修复此警告。
确保link
的初始值不是null
或undefined
,而是一个空字符串,如:
// const [link, setLink] = React.useState() // will cause the warning
const [link, setLink] = React.useState('') // correct
编辑:
编辑问题后,发现问题:
输入“文件”类型的标签MUST BE UNCONTROLLED。您不应将 value
或 onChange
传递给它。相反,您应该传递一个引用并将其附加到输入。
const arquivo = useRef(null);
return (
<React.Fragment>
// ...
<input
type="file"
ref={arquivo}
id="arquivo"
/>
</React.Fragment>
)
这也是一种罕见的情况,您希望隐藏 DOM 节点而不是避免渲染。 File对象直接存放在DOM上,所以一定要保留这个DOM节点,否则会丢失选中的文件。
<input
type="file"
ref={arquivo}
id="arquivo"
style={{ display: forma_envio !== "File" && "none" }}
/>
完整代码位于 CodeSandbox,没有警告。
在一个使用 React 的应用程序中,我有一个 form
和 radio
输入,它选择要呈现的组件,但是当我更改单选选项时,会显示此警告 -
“组件正在将类型文件的不受控输入更改为受控。输入元素不应从不受控切换为受控(反之亦然)。在组件的生命周期内决定使用受控或不受控输入元素“
表格
import React, { useState } from "react";
export default () => {
const [link, setLink] = useState("");
const [arquivo, setArquivo] = useState("");
const [forma_envio, setFormaEnvio] = useState("");
return(
<React.Fragment>
<div className="form-check ">
<input
type="radio"
className="form-check-input"
name="forma"
id="forma1"
value="File"
checked={forma_envio === "File"}
onChange={(e) => {
setFormaEnvio(e.target.value);
}}
/>
</div>
<div className="form-check ">
<input
type="radio"
className="form-check-input"
name="forma"
id="forma2"
value="Link"
checked={forma_envio === "Link"}
onChange={(e) => {
setFormaEnvio(e.target.value);
}}
/>
</div>
{forma_envio === "File" ? (
<input
type="file"
className="form-control-file form-control"
id="arquivo"`
onChange={(e) => {
e.preventDefault();
handleUpload(e.target.files[0]);
}}
/>
) :forma_envio === "Link" (
<input
value={link}
type="text"
className="form-control"
id="link"
onChange={(e) => {
e.preventDefault();
setLink(e.target.value);
}}
/>
):
("")}
</React.Fragment>
);
}
所有州都以 ""
开头。
一切正常,但我仍然不知道如何修复此警告。
确保link
的初始值不是null
或undefined
,而是一个空字符串,如:
// const [link, setLink] = React.useState() // will cause the warning
const [link, setLink] = React.useState('') // correct
编辑: 编辑问题后,发现问题:
输入“文件”类型的标签MUST BE UNCONTROLLED。您不应将 value
或 onChange
传递给它。相反,您应该传递一个引用并将其附加到输入。
const arquivo = useRef(null);
return (
<React.Fragment>
// ...
<input
type="file"
ref={arquivo}
id="arquivo"
/>
</React.Fragment>
)
这也是一种罕见的情况,您希望隐藏 DOM 节点而不是避免渲染。 File对象直接存放在DOM上,所以一定要保留这个DOM节点,否则会丢失选中的文件。
<input
type="file"
ref={arquivo}
id="arquivo"
style={{ display: forma_envio !== "File" && "none" }}
/>
完整代码位于 CodeSandbox,没有警告。