如何为相同状态保存不同的输入值

时间:2019-01-30 12:24:19

标签: javascript reactjs

我有一个包含多个组件的表,并且在更改所选输入的值时,我想将新值保存在父状态中,如下所示(以便我可以这样提交):

monday: {startTime: '08:00', endTime: '23:00'}

是否可以使用一个onChange函数来执行此操作?如果没有,如何使用多个处理功能来实现? 请记住,这要在一周中的所有日子中完成。

Live example here

父组件:

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

    this.state = {
      editMode: false,
      friday: { endTime: "", startTime: "" },
      monday: { endTime: "", startTime: "" },
      thursday: { endTime: "", startTime: "" },
      tuesday: { endTime: "", startTime: "" },
      wednesday: { endTime: "", startTime: "" },
      saturday: { endTime: "", startTime: "" },
      sunday: { endTime: "", startTime: "" }
    };
  }

  handleInput = e => {
    let value = e.target.value;
    let name = e.target.name;
    console.log(value);

    this.setState(
      {
        monday: { startTime: value, endTime: "" }
      },
      () => console.log(this.state)
    );
  };

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

    this.setState({
      editMode: false
    });
  };

  render() {
    return (
      <div className="App">
        <Table
          onSubmit={this.handleFormSubmit}
          onChange={this.handleInput}
          edit={this.state.editMode}
        />
        <div>
          {!this.state.editMode ? (
            <button onClick={() => this.setState({ editMode: true })}>
              edit
            </button>
          ) : (
            <div>
              <button onClick={() => this.setState({ editMode: false })}>
                cancel
              </button>
              <button onClick={this.handleFormSubmit}>save</button>
            </div>
          )}
        </div>
      </div>
    );
  }
}

表组件:

    export default class Table extends React.Component {
    constructor(props) {
        super(props);

    this.state = {
      weekDays: moment.weekdays(true)
    };
  }

  submitTime = data => {
    this.props.onSubmit(data);
  };

  render() {
    return (
      <table style={{ textAlign: "center" }}>
        <thead>
          <tr>
            <td style={{ opacity: 0 }} />
            {this.state.weekDays.map(day => {
              return (
                <td key={day}>
                  <p>{day}</p>
               </td>
              );
            })}
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>
              <p>Opening:</p>
            </td>
            {[0, 1, 2, 3, 4, 5, 6].map(open => {
              return (
                <td key={open}>
                  {this.props.edit ? (
                    <form onSubmit={this.props.onSubmit}>
                      <input
                        onChange={this.props.onChange}
                        placeholder="open time"
                        defaultValue={open}
                      />
                    </form>
                  ) : (
                    <p>{open}</p>
                  )}
                </td>
              );
             })}
          </tr>
          <tr>
             <td>
              <p>Closing:</p>
            </td>
            {[0, 1, 2, 3, 4, 5, 6].map(close => {
              return (
                <td key={close}>
                  {this.props.edit ? (
                    <form onSubmit={this.props.onSubmit}>
                      <input
                        onChange={this.props.onChange}
                        placeholder="close time"
                        defaultValue={close}
                      />
                    </form>
                  ) : (
                    <p>{close}</p>
                   )}
                </td>
              );
            })}
          </tr>
        </tbody>
      </table>
    );
  }
}

谢谢!

2 个答案:

答案 0 :(得分:2)

在每个onChange的{​​{1}}函数中,您可以将输入的索引作为参数发送:

input

您现在必须向处理函数添加另一组参数:

{[0, 1, 2, 3, 4, 5, 6].map(close => {
    return (
        <td key={close}>
            {this.props.edit ? (
                <form onSubmit={this.props.onSubmit}>
                    <input
                        onChange={this.props.onChange(close)}

最后一步是将索引简单地映射到正确的日期:

handleInput = index => e => {

并根据所选日期修改状态:

const day = ['monday', 'tuesday', 'wednesday'...][index]

就个人而言,我建议直接在整天的时间而不是this.setState( { [day]: { startTime: value, endTime: "" } } ) 进行映射以删除步骤,但这取决于您。


编辑

刚刚看到您的代码,因为您有两种输入类型,所以可能会导致其他问题。要区分发送的值,您可以做与之前完全相同的操作,然后发送要修改的值的类型:

开始时间:

[0, 1, 2, 3, 4, 5, 6]

结束时间:

<input
    onChange={this.props.onChange(open, 'startTime')}
    placeholder="close time"
    defaultValue={close}
/>

然后更改您的处理函数以获取参数:

<input
    onChange={this.props.onChange(close, 'endTime')}
    placeholder="close time"
    defaultValue={close}
/>

现在最棘手的部分是handleInput = (index, type) => e => { 。您无法更新嵌套对象中的单个元素,必须解构旧对象并覆盖相应的值:

setState

答案 1 :(得分:0)

是的,可以这样做。它的工作方式与更新任何对象相同。

let monday = Object.assign({}, this.state.monday)
monday.startTime = value_1
monday.endTime = value_2

this.setState({ monday: monday })

请注意Object.assign()的使用。如果您不创建对象的副本,那么您将直接更新状态。例如:

let monday = this.state.monday
monday.startTime = value_1

与执行相同:

this.state.monday = value_1

您绝对不应该在React中这样做。