【问题标题】:Save values in array of data将值保存在数据数组中
【发布时间】:2020-09-29 18:47:51
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: javascript reactjs


    【解决方案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>

    【讨论】:

    • 看起来不错,但是如果用户在点击Add Field后添加了2个字段,现在他想删除一对字段,如何添加删除功能?
    • 然后孩子应该公开另一个方法,比如“onDeleteField”,它接受参数nr, index,里面会有setItems(items =&gt; {,它用user数组过滤来计算新项目
    • 另外,我不明白为什么如果我第二次单击Add Field,代码会在 finputs 上添加 2 对而不是一对。你能改变吗?提前致谢
    • 输入对是名字和姓氏,如示例中所示
    • 当我第一次点击Add Field时它工作正常,但如果我想第二次点击它添加:2个用户名输入和2个姓氏,但应该是1个用户名和1 有姓氏。请告诉我,如果你明白我想说的话。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-09
    • 2017-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多