如何在Reactjs中保存输入字段?

时间:2020-05-16 17:11:30

标签: javascript reactjs react-hooks

我创建了两个组件AppInner组件App组件包含一个表单。

我的内部组件包含一个const数据,我进一步将其传递给危险地设置内部HTML以设置内部html。因此可以有任意数量的输入字段。有时它可以有3到5个输入字段。

在React中有可能吗?如我所见,在这种情况下我无法进行两种方式的绑定。

我认为这在React中是不可能的吗?

Demo Link

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>
  );
}

1 个答案:

答案 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>
  );
}

Here's a demo