React - 区分表单上动态生成的输入

React - differentiating between dynamically generated inputs on a form

我有一个 table 中的数据输入表单,它根据有多少列生成输入。然而,我正在努力将输入分开,这样当我更改其中一个输入的值时,所有输入都会发生变化。有什么方法可以区分它们,以便我可以在每个输入中输入不同的值。我正在使用带有助焊剂的 React。

这是我目前正在使用的代码:

import React from 'react';
import AppStore from '../../stores/AppStore';

export default class RowForm extends React.Component {
    state = {input: ''};
    onChange = (e) => {
        this.setState({input: e.target.value});
        console.log(input);
    };

    editStop = () => {
        this.props.editStop();
    };

    handleSubmit = (e) => {
        e.preventDefault();

        let access_token = AppStore.getToken();
        let id = AppStore.getTable().id;

        this.props.handleSubmit(access_token, id);

    };

    render() {

        let {input} = this.state;
        let dataEntries = AppStore.getTable().columns; //this gets the amount of columns so I can map through them and generate the correct amount of inputs.

        return (
            <tr>
                {dataEntries.map((element, index) => {
                    return (
                        <td key={index}><input type="text" className="form-control" id={element.id} placeholder="enter data" value={this.state.input} onChange={this.onChange} /></td>
                    );
                })}
                <td>
                    <button className="btn btn-default" onClick={this.editStop}><i className="fa fa-ban"></i>Cancel</button>
                    <button className="btn btn-success" onClick={this.handleSubmit}><i className="fa fa-check"></i>Save</button>
                </td>
            </tr>
        );
    }
} 

非常感谢任何帮助,尤其是示例!

感谢您的宝贵时间

您可以在 onChange 处理程序中创建一个匿名函数:

<input key={index} onChange={event => this.onChange(event, index)}/>

但是,更大的问题是您没有将 AppStore.getTable().columns 映射到任何地方的状态,因此您根本无法修改组件状态。此外,您在 React 中不正确地使用 ES6 类。

class RowForm extends React.Component {
  constructor (props) {
    super(props);

    this.state = {
      inputs: {0: null, 1: null, 2: null}
    };
  }

  onChange (event, index) {
    this.setState({inputs[index]: event.target.value});
  }
}

如果您需要映射 AppStore.getTable().columns,您应该将该数据作为 props 传递下去。将道具映射到状态是一种反模式。

class App extends React.Component {
  constructor () { // initialize stuff... }

  componenDidMount () {
    this.setState({columns: AppStore.getTable().columns});
  }

  onChange (event, index) {
    this.setState({columns[index]: event.target.value});
  }

  render () {
    <RowForm columns={this.state.columns} handleChange={this.onChange}/>
  }
}

class RowForm extends React.Component {
  constructor (props) {
    super(props);
  }

  render () {
    <div>
      {this.props.columns.map(index => {
        return <input onChange={event => this.props.handleChange(event, index)}/>
      })}
    </div>
  }
}

但是,这不会在调用 onChange 时更新 AppStore。为此,您需要以某种方式跟踪全局状态。我建议查看 Redux.


更新答案以尝试使用当前条件修复代码:

class RowForm extends React.Component {
  // Set `dataEntries` to an empty array. This will prevent errors
  // from appearing in between `render` and `componentDidMount`.
  // e.g.: `this.state.dataEntries.map` is undefined or not an Array.
  // You may want to make this a little bit more fail safe though.
  state = {dataEntries: []};

  onChange = (event, element) => {
      // This assumes `element` is a string based on the column name.
      this.setState({dataEntries[element]: event.target.value});
  }

  componentDidMount () {
      // Set state with columns from the table.
      // Whenever this component mounts it will reset to the state
      // from `AppStore` unless you set up event listeners like in
      // Flux or migrate to Redux

      // This also assumes that `getTable().columns` returns an array
      // of column names. I don't know what your data structure looks
      // like so it's hard for me to help here. You need to turn the
      // array into an object to store values in the keys.

      let dataEntries = AppStore.getTable().columns.reduce((obj, name) => {
          obj[name] = null;
          return obj;
      }, {});
      this.setState({dataEntries});
  }

  render () {
        let {dataEntries} = this.state;

        // It is not really recommended to use indexes here because
        // of the way React diffing works. If `element` is a string
        // you can use that as the key/index instead. Also, it needs
        // to be unique within the array.
        // Turn dataEntries back into an array so map will work properly.   
        return (
            <tr>
                {Object.keys(dataEntries).map((element) => {
                    return (
                        <td key={element}><input type="text" className="form-control" id={element} placeholder="enter data" value={dataEntries[element]} onChange={event => this.onChange(event, element)} /></td>
                    );
                })}
                <td>
                    <button className="btn btn-default" onClick={this.editStop}><i className="fa fa-ban"></i>Cancel</button>
                    <button className="btn btn-success" onClick={this.handleSubmit}><i className="fa fa-check"></i>Save</button>
                </td>
            </tr>
        );
    }
}