【问题标题】:How to save input entered by the user in a state which is an array in React如何将用户输入的输入保存为 React 中的数组状态
【发布时间】:2019-09-26 20:47:32
【问题描述】:

整个想法是让用户在表单中输入并在 JSON 对象中显示他们的输入。在状态下,我有一个数组,里面还有另一个数组。

我的 Form.js 是这样的,

state= {
    groups:[{
      typeA:[{}],
      typeB:[{}]
    }],
    credentials: false
    };

    change = e =>{
        this.setState({[e.target.name]: e.target.value})
    };

    handleSubmit(event) {
        event.preventDefault();
        this.setState({
          credentials: true 
        });
      }
render(){
        return(
            <div class="classform">
            <form >
                <label>
                    Field1:
                    <br/>
                    <input type="text"
                    name="typeA"
                    placeholder="Type A"
   //store it as the first element of the type A
                    value={this.state.groups.typeA[0]} 
                    onChange={this.change.bind(this)}
                 />
  //other fields with the same code

随后,Field2 将被存储为类型 A 的第二个元素 然后,Field3 和 Field4 将被存储为 B 类型数组的 2

我希望代码能给我这样的输出:

"typeA": ["field1 value", "field2 value"],
"typeB": ["field3 value", "field4 value"]}

我是 React 的初学者,我无法将字段值存储为数组状态。

【问题讨论】:

    标签: javascript arrays reactjs state


    【解决方案1】:

    为了简单起见,我将推荐以下解决方案, 您可以管理不同状态变量中的输入值,并在提交时将它们更改为您想要的输出,而不是在状态中使用嵌套数组。

    state = {
      field1: '',
      field2: '',
      field3: '',
      field4: '',
    }
    change = e => {
      this.setState({[e.target.name]: e.target.value})
    };
    
    handleSubmit(event) {
      event.preventDefault();
      const { field1, field2, field3, field4 } = this.state;
      // This is your output
      const output = [{typeA: [field1, field2], typeB: [field2, field3]}];
      this.setState({
        credentials: true 
      });
    }
    
    render(){
      return(
        <div class="classform">
          <form >
            <label>
              Field1:
              <br/>
              <input type="text"
                name="field1"
                placeholder="Type A"
                value={this.state.field1}
                onChange={this.change}
              />
            </label>
            <label>
              Field2:
              <br/>
              <input type="text"
                name="field2"
                placeholder="Type A"
                value={this.state.field2}
                onChange={this.change}
              />
            </label>
    

    【讨论】:

      【解决方案2】:

      试试这个:

      import React, { Component } from "react";
      
      export default class App extends Component {
        constructor(props) {
          super(props);
      
          this.state = {
            groups: [
              {
                typeA: [{}],
                typeB: [{}]
              }
            ],
            credentials: false
          };
        }
      
        change = (e, key) => {
          let { groups } = this.state;
      
          let myVal = groups[0][e.target.name];
          // or if you want to add value in an object likr [{value: 'abcd'}]
          myVal[0][key] = e.target.value;
          groups[0][e.target.name] = myVal;
          console.log("TCL: App -> groups", groups);
          this.setState({ groups });
        };
      
        render() {
          return (
            <div>
              <input
                type="text"
                name="typeA"
                placeholder="Type A"
                value={this.state.groups[0].typeA[0].value2}
                onChange={e => this.change(e, "value2")}
              />
              <input
                type="text"
                name="typeA"
                placeholder="Type A2"
                value={this.state.groups[0].typeA[0].value}
                onChange={e => this.change(e, "value")}
              />
              <br />
              <input
                type="text"
                name="typeB"
                placeholder="Type b"
                value={this.state.groups[0].typeB[0].value}
                onChange={e => this.change(e, "value")}
              />
            </div>
          );
        }
      }
      
      
      

      【讨论】:

      • 这给了我一个错误 TypeError: Unable to get property '0' of undefined or null reference。我是否也需要更改输入标签内的“名称”
      • 仍然报同样的错误。我还尝试了 myVal = groups[e.target.name][0] (这样它就需要 name="typeA" 然后插入 [0] index )。你认为我应该使用地图来分配数组值吗?
      • 你能再试一次吗!
      • 不!仍然无法正常工作:(它甚至没有进入 return 。给出相同的错误“TypeError: Unable to get property '0' of undefined or null reference”
      • 哇!有效!对于后续列,只有一件事,例如 col2(typeA 数组的第二个元素)和 col 3 和 col 4(typeB 数组中的两个元素)。应该如何改变价值观?假设我将
        包装在 map 函数中,但是我应该如何更改 chnage 函数中的值索引
      【解决方案3】:

      给每个输入一个自定义属性,例如data-group="typeA"。在您的 on change 函数中获取该值并将这些值添加到正确的数组中。

      <input
        type="text"
        name="col2"
        placeholder="Type A"
        data-group="typeA" // add custom attribute typeA | typeB etc.
        onChange={e => this.change(e)}
      />
      

      在您的更改句柄中获取自定义属性,并使用它将值添加到正确的数组中。

      change = e => {
      
        // create a copy of  this.state.groups
        const copyGroups = JSON.parse(JSON.stringify(this.state.groups));
      
        // get data-group value
        const group = event.target.dataset.group;
      
        if (!copyGroups[0][group]) {
          copyGroups[0][group] = []; // add type if it doesn't exists
        }
      
        const groups = copyGroups[0][group];
        const index = this.findFieldIndex(groups, e.target.name);
      
        if (index < 0) {
          // if input doesn't exists add to the array
          copyGroups[0][group] = [...groups, { [e.target.name]: e.target.value }];
        } else {
          // else update the value
          copyGroups[0][group][index][e.target.name] = e.target.value;
        }
      
        this.setState({ groups: copyGroups });
      };
      

      pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; }
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
      <div id="root"></div>
      
      <script type="text/babel">
      
      function formatState(json) {
        if (typeof json != 'string') {
             json = JSON.stringify(json, undefined, 2);
        }
        json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
        return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, (match) => match);
      }
      
      const Credentials = ({ value }) => {
        return <pre>{formatState(value)}</pre>;
      };
      
      class App extends React.Component {
        state = {
          groups: [
            {
              typeA: [],
              typeB: []
            }
          ],
          credentials: false
        };
      
        handleSubmit = event => {
          event.preventDefault();
      
          this.setState({
            credentials: true // display Credentials  component
          });
        };
      
        // get the current input index in the array typeA | typeB
        findFieldIndex = (array, name) => {
          return array.findIndex(item => item[name] !== undefined);
        };
      
          change = e => {
      
            // create a copy of  this.state.groups
            const copyGroups = JSON.parse(JSON.stringify(this.state.groups));
      
            // get data-group value
            const group = event.target.dataset.group;
            
            if (!copyGroups[0][group]) {
              copyGroups[0][group] = []; // add new type
            }
            
            const groups = copyGroups[0][group];
            const index = this.findFieldIndex(groups, e.target.name);
      
            if (index < 0) {
              // if input doesn't exists add to the array
              copyGroups[0][group] = [...groups, { [e.target.name]: e.target.value }];
            } else {
              // update the value
              copyGroups[0][group][index][e.target.name] = e.target.value;
            }
      
            this.setState({ groups: copyGroups });
          };
          
       removeKey = (key) => {
          const temp = {...this.state};
          delete temp[key];
          return temp;
       }
      
        render() {
          return (
            <div>
              <input
                type="text"
                name="col1"
                placeholder="Type A"
                data-group="typeA"
                onChange={e => this.change(e)}
              />
      
              <input
                type="text"
                name="col2"
                placeholder="Type A"
                data-group="typeA"
                onChange={e => this.change(e)}
              />
      
              <input
                type="text"
                name="col2"
                placeholder="Type B"
                data-group="typeB"
                onChange={e => this.change(e)}
              />
              
              <input
                type="text"
                name="typec"
                placeholder="Type C | New Type"
                data-group="typeC"
                onChange={e => this.change(e)}
              />
              
              <input
                type="text"
                name="typed"
                placeholder="Type D | New Type"
                data-group="typeD"
                onChange={e => this.change(e)}
              />
      
              <button onClick={this.handleSubmit}>Submit</button>
              {this.state.credentials && (
                <Credentials value={JSON.stringify(this.removeKey('credentials'), undefined, 2)} />
              )}
            </div>
          );
        }
      }
      
      ReactDOM.render(
          <App />,
          document.getElementById('root')
      );
      </script>

      【讨论】:

      • 天哪!凉爽的!谢谢!你能告诉我如何在不打印凭据的情况下打印出 JSON 对象:真的吗?我只是用它来打印出 JSON 对象
      • 好的,我明白了!谢谢
      • 是的,我明白了!感谢您的帮助
      • 嗨,Junis,我有一个问题,这只是对这个问题的延伸。我想知道是否有办法将输入值存储为数组(并且只是值)。假设,如果我有一个列的开始日期和结束日期:我想以数组的形式存储这些值。所以,我需要这样的输出:typeA: [ [col1value1, col1value2], [startdate, enddate]]。我知道这很复杂,但我的输出应该是这样的。没关系,即使我实际上没有将它存储在数组中
      猜你喜欢
      • 1970-01-01
      • 2020-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-25
      • 1970-01-01
      • 2017-09-03
      相关资源
      最近更新 更多