我创建了两个组件App
和Inner
组件App组件包含一个表单。
我的内部组件包含一个const数据,我进一步将其传递给危险地设置内部HTML以设置内部html。因此可以有任意数量的输入字段。有时它可以有3到5个输入字段。
在React中有可能吗?如我所见,在这种情况下我无法进行两种方式的绑定。
我认为这在React中是不可能的吗?
export default function App() {
const handleSubmission = e => {
e.preventDefault();
};
return (
<div className="App">
<Inner />
<form onSubmit={handleSubmission}>
<div>Both two values comma separated: </div>
<button type="submit"> Submit </button>
</form>
</div>
);
}
const data = {
htmltag: `<html><style>table { font-family: arial, sans-serif; border-collapse: collapse; width: 40%;}td, th { border: 1px solid #dddddd; text-align: left; padding: 8px;}tr:nth-child(even) { background-color: #dddddd;}</style><body> <table> <tbody> <tr> <th>1</th> <th>2</th> </tr> <tr> <td>Hello</td> <td><input type = "text" /></td> </tr> <tr> <td>Welcome</td> <td><input type = "text" /></td> </tr> </tbody> </table> </body></html>`
};
export default function Inner() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<div dangerouslySetInnerHTML={{ __html: data.htmltag }} />
</div>
);
}
答案 0 :(得分:1)
您将无法以React类型的方式访问此数据,但是您可以使用React支持的普通JavaScript来访问此数据。基本上,您不能将这些输入视为controlled components,而不能视为uncontrolled components。
但是,这意味着您将不会像使用受控组件那样实时获取状态更新,但仍可以访问数据。您只需在需要时(例如,在提交时)从DOM中获取数据。
由于您还将无法将引用直接传递给这些组件,因此必须查询DOM。您可以从容器的ref(容器的内部HTML危险设置)开始,然后查询input
元素(和/或其他类似输入的元素)。
这是一个例子:
App.js
export default function App() {
const dataContainerRef = React.useRef(null);
const handleSubmission = e => {
e.preventDefault();
const inputs = Array.from(dataContainerRef.current.querySelectorAll("input"));
// if your inputs have unique names:
const formData = Object.fromEntries(inputs.map(input => [input.name, input.value]));
// or just get an array of the values:
const formDataArray = inputs.map(input => input.value);
};
return (
<div className="App">
<Inner dataContainerRef={ dataContainerRef } />
<form onSubmit={handleSubmission}>
<div>Both two values comma separated: </div>
<button type="submit"> Submit </button>
</form>
</div>
);
}
Inner.js
export default function Inner(props) {
const { dataContainerRef } = props;
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<div
ref={dataContainerRef}
className="data-container"
dangerouslySetInnerHTML={{ __html: data.htmltag }}
/>
</div>
);
}
这里是codesandbox demo。
请注意,如果您想了解其他使用纯JS来获取表单数据的方法,可以使用this question about getting form data with JS(我建议不将jQuery导入到React项目中) )。
替代方法
如果您愿意更改数据结构,以使data
不是HTML字符串而是JSON格式,则可以自己动态创建input
元素并控制它们像往常一样。
例如,如果您这样构造data
:
const data = {
inputNames: ["Hello", "Welcome"],
}
然后您可以创建以下格式的formData
:
{
Hello: "",
Welcome: "",
}
应该存储在Inner
的父级中,因为它拥有提交功能。
然后,您只需要从formData
初始化data
,然后为每个给定的input
动态创建一个inputName
元素。
以下是Inner
的示例:
export default function Inner(props) {
const { formData, setFormData } = props;
React.useEffect(() => {
// initialize `formData`
setFormData(
Object.fromEntries(data.inputNames.map(inputName => [inputName, ""]))
);
}, [setFormData]);
const inputRows = data.inputNames.map(inputName => (
<tr key={inputName}>
<td>{inputName}</td>
<td>
<input
name={inputName}
value={formData[inputName]}
onChange={event => {
event.persist();
setFormData(prev => ({
...prev,
[event.target.name]: event.target.value
}));
}}
/>
</td>
</tr>
));
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<table>
<tbody>{inputRows}</tbody>
</table>
</div>
);
}