将值保存在数据数组中

IT技术 javascript reactjs
2021-05-02 07:25:10

我的react应用程序从用户那里获取数据,并在用户单击SUBMIT按钮时输出它们现在用户打开应用程序出现一个数字输入。在那里他可以设置一个数字,例如 2。之后会出现 2 个框,用户可以add fields在其中点击按钮+在每个字段中,用户必须添加他的名字和姓氏。现在应用程序可以工作,但没有以正确的方式。
现在,如果用户在第一个框中添加他的用户名和姓氏并点击SUBMIT,everithing 出现在:

 const onFinish = values => {
    const res = {
      data: [dataAll]
    };
    console.log("Received values of form:", res);
  };

但是如果用户点击add fields按钮添加另一个输入 ,第一个数据就会消失。同样的问题是当用户在 2 个框中添加数据时,数据仅从最后一个框中保存。

function handleInputChange(value) {
    const newArray = Array.from({ length: value }, (_, index) => index + 1);
    setNr(newArray);
  }

  const onFinish = values => {
    const res = {
      data: [dataAll]
    };
    console.log("Received values of form:", res);
  };

  return (
    <div>
      <Form name="outter" onFinish={onFinish}>
        {nr.map(i => (
          <div>
            <p key={i}>{i}</p>
            <Child setDataAll={setDataAll} nr={i} />
          </div>
        ))}
        <Form.Item
          name={["user", "nr"]}
          label="Nr"
          rules={[{ type: "number", min: 0, max: 7 }]}
        >
          <InputNumber onChange={handleInputChange} />
        </Form.Item>
        <Form.Item>
          <Button htmlType="submit" type="primary">
            Submit
          </Button>
        </Form.Item>
      </Form>
    </div>
  );
};

点击提交后的 Mu 预期结果是:

data:[
       {
  nr:1,
  user: [
      {
      firstName:'John',
      lastName: 'Doe'
      },
      {
      firstName:'Bill',
      lastName: 'White'
      }
       ]
       },
              {
  nr:2,
  user: [
      {
      firstName:'Carl',
      lastName: 'Doe'
      },
      {
      firstName:'Mike',
      lastName: 'Green'
      },
      {
      firstName:'Sarah',
      lastName: 'Doe'     
      }
       ]
       }, 
     ]
   ....  
     // object depend by how many fields user added in each nr

问题:如何实现上述结果?
演示:https : //codesandbox.io/s/wandering-wind-3xgm7?file=/ src/Main.js: 288-1158

1个回答

这是一个如何做到的示例。

如您所见,Child变成了展示组件,只显示数据。

其余的逻辑转到父组件。

const { useState, useEffect, Fragment } = React;

const Child = ({nr, user, onAddField, onChange}) => {

  return <div>
    <div>{nr}</div>
    {user.map(({firstName, lastName}, index) => <div key={index}>
    <input onChange={({target: {name, value}}) => onChange(nr, index, name, value)} value={firstName} name="firstName" type="text"/>
    <input onChange={({target: {name, value}}) => onChange(nr, index, name, value)} value={lastName} name="lastName" type="text"/>
    </div>)}
    <button onClick={() => onAddField(nr)}>Add Field</button>
  </div>
}

const App = () => {
  const [items, setItems] = useState([
  {
    nr: 1,
    user: []
  },
  {
    nr: 2,
    user: [
      {firstName: 'test1', lastName: 'test1'},
      {firstName: 'test2', lastName: 'test2'}
    ]
  }
  ]);  

  const onCountChange = ({target: {value}}) => {
    
    setItems(items => {
      const computedList = Array(Number(value)).fill(0).map((pr, index) => ({
        nr: index + 1,
        user: []
      }))
      
      const merged = computedList.reduce((acc, value) => {
        const item = items.find(pr => pr.nr === value.nr) || value;
        
        acc = [...acc, item];
        
        return acc;
      }, [])
      
      return merged;
    })
    
  }

  const onChildChange = (nr, index, name, value) => {
    setItems(items => {
      const newItems = [...items];
      const item = newItems.find(pr => pr.nr === nr);
      const field = item.user.find((pr, ind) => index === ind)
      field[name] = value;
      
      return newItems;
    });
  }
  
  const onAddField = (nr) => {
    setItems(items => {

      const newItems = [...items];
      const item = newItems.find(pr => pr.nr === nr);
      item.user = [...item.user, {
        firstName: '',
        lastName: ''
      }];

      return newItems;
    })
  }

  const onClick = () => {
    console.log({data: items});
  }

  return <div>
    {items.map((pr, index) => <Child {...pr} onAddField={onAddField} onChange={onChildChange} key={index} />)}
    <input onChange={onCountChange} value={items.length} type="number"/>
    <button onClick={onClick}>Submit</button>
  </div>
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
  );
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>