【问题标题】:How do I create an object from data in React?如何从 React 中的数据创建对象?
【发布时间】:2020-09-28 12:56:59
【问题描述】:

根据下面的代码,你如何创建一个 React 状态的对象模型(对于一个函数组件)?

<div class="form-row">
    <label>Input 1</label>
    <input id="1" />
</div>

<div class="form-row">
    <label>Input 2</label>
    <input id="2" />
</div>

<div class="form-row">
    <label>Input 3</label>
    <input id="3" />
</div>

<div class="form-row">
    <label>Input 4</label>
    <input id="4" />
</div>
const dataToPost = [
        ...document.querySelectorAll("div.form-row"),
    ].map((f) => {
        let obj = {};
        f.querySelectorAll("input").forEach(
            (item) => (
                (obj["id"] = item.id), (obj["value"] = item.value || "")
            )
        );
        return obj;
    });

这会输出我想要的结果...

"dataToPost": [
    {
        "id": "1",
        "value": "input one value"
    },
    {
        "id": "2",
        "value": "input two value"
    },
    {
        "id": "3",
        "value": "input three value"
    },
    {
        "id": "4",
        "value": "input four value"
    }
]

那么是否可以为每个输入使用 on change 事件来更新它的状态对象,因为它需要是一个 Function 组件?

【问题讨论】:

  • 您可以在输入 id 上创建对象,而不是 div。
  • 你确定这是你想做的吗?通常,数据流是相反的:你从后端获得一些 JSON 结构,并在此基础上呈现前端。我从来没有见过一个有效的用例(在我 12 年的 IT 开发经验中)来解析 HTML 结构并从中生成 JSON...但是如果我错了请告诉我...
  • 嗨,你就在那儿! JSON 通过一个简单的 Input 组件来提供 HTML 中的每个表单行。但不确定如何在上述场景中使用状态,因为 JSON 是动态的并且输入可能会有所不同,因此不确定如何在 React useState 中以正确的方式监听所有呈现的输入的变化并正确更新 onChange 跨度>
  • this你想做什么?
  • @Yousaf 是的,这就是我想要做的!谢谢你:)

标签: javascript html reactjs state


【解决方案1】:

您需要创建一个自定义挂钩以将表单的状态保持为您想要的格式,并在 onChange 事件上更新表单状态

按照以下步骤操作:

  1. 转换

    <div class="form-row">
        <label>Input 1</label>
        <input id="1" />
    </div>
    

    插入到将表示单个输入元素及其标签的组件中。

  2. 创建一个保持表单状态的自定义钩子

    import { useState, useCallback } from "react";
    
    function useForm() {
      const [data, setData] = useState([
        { id: 1, value: "" },
        { id: 2, value: "" },
        { id: 3, value: "" },
        { id: 4, value: "" }
      ]);
    
      const updateForm = useCallback(
        ({ target }) => {
            const arr = [...data];
            const obj = arr.find(o => o.id === Number(target.name));
    
            obj.value = target.value;
            setData(arr);
        },
        []
      );
    
      return [data, updateForm];
    }
    
    export default useForm;
    
  3. 创建一个Form 组件,它将渲染所有Input 组件。这个Form 组件将使用在第2 步中创建的useForm 钩子。在这个组件中,我们将循环表单状态并渲染各个Input 组件并将适当的道具传递给Input 元素以及传递onChange 事件处理程序,该处理程序将在任何输入更改时更新表单状态。

    import React from "react";
    import useForm from "./useForm";
    import Input from './Input';
    
    function Form() {
       const [data, setData] = useForm();
    
       return (
        <>
          {
            data.map((input, idx) => (
               <Input
                  key={idx}
                  type="text"
                  value={input.value}
                  label={`Input ${++idx}`}
                  name={input.id}
                  setValue={setData}
               />
            ))
           }
        </>
      );
    }
    
    export default Form;
    

这是上述步骤的working demo

附: useCallback hook 和 React.memo 已用于优化。这可以防止在任何Input 组件上触发onChange 事件时对所有Input 组件进行不必要的重新渲染

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-02
    • 1970-01-01
    • 2010-09-27
    • 2020-07-10
    • 1970-01-01
    • 2015-05-24
    • 1970-01-01
    • 2015-08-02
    相关资源
    最近更新 更多