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

时间:2016-03-01 15:33:31

标签: reactjs reactjs-flux

我有一个表格中数据的输入表单,根据有多少列生成输入。我正在努力分离输入但是当我在一个中更改一个值时,所有输入都会发生变化。有什么方法可以区分它们,以便我可以在每个输入中输入不同的值。我正在使用React和flux。

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

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

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

感谢您的时间

1 个答案:

答案 0 :(得分:1)

您可以在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,则应将该数据作为道具传递下来。将道具映射到州是一种反模式。

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

但是,在调用AppStore时,这不会更新onChange。为此你需要以某种方式跟踪全球状态。我建议您查看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>
        );
    }
}