【问题标题】:How to save input field in Reactjs?如何在 Reactjs 中保存输入字段?
【发布时间】:2020-09-02 13:01:58
【问题描述】:

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

我的内部组件包含一个 const 数据,我进一步将它传递给 dangerouslySetInnerHTML 以设置内部 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>
  );
}

【问题讨论】:

  • 你的意思是保存输入值吗?
  • 您与使用dangerouslySetInnerHTML 的关系如何?是否可以在您的项目中将数据更改为 JSON 格式?如果您愿意切换,我对此也有一些想法。

标签: javascript reactjs react-hooks


【解决方案1】:

您将无法以 React 类型的方式访问这些数据,但是您可以使用 React 支持的纯 JavaScript 访问这些数据。基本上你不能把这些输入当作controlled components,而是当作uncontrolled components

这意味着您不会像使用受控组件那样实时获得状态更新,但您仍然可以访问数据。您只需在需要时(例如在提交时)从 DOM 获取数据。

由于您也无法将 refs 直接传递给这些组件,因此您必须查询 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的父级中,因为它拥有提交功能。

然后您只需要从data 初始化formData,然后为给定的每个inputName 动态创建一个input 元素。

这是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.

【讨论】:

  • 能给个codeandbox的demo吗?因为它没有运行@Henry Woody
  • @Khushboo 我想是的,您只需将表单数据传递给handleSubmit 中所需的任何函数。我还用另一种方法更新了我的答案。
猜你喜欢
  • 2020-11-24
  • 2022-10-04
  • 1970-01-01
  • 2011-08-15
  • 2021-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多