为什么更改子组件中的状态(基于道具)会影响道具?

时间:2018-07-23 02:46:02

标签: javascript reactjs

您可以观看演示here。尝试单击“编辑”按钮并更改输入字段的值。

在父组件中,它将对象数组传递给它的子组件。在子组件内部,可以将一个对象传递到其状态,名为editedTodo。但是,奇怪的是,当editedTodo更改时,道具也随之更改。

这不是我想要的。有人可以帮助我解决这个问题吗?

这里是todo组件:

import React from "react";

export default class extends React.Component {
  state = {
    editedTodo: null
  };

  toggleEditTodo = (todo = null) => {
    this.setState({ editedTodo: todo });
  };

  onChangeTodoText = text => {
    this.setState(prevState => ({
      editedTodo: Object.assign(prevState.editedTodo, { text })
    }));
  };

  submitTodoForm = e => {
    e.preventDefault();
    this.props.saveEditedTodo(this.state.editedTodo);
    this.setState({
      editedTodo: null
    });
  };

  render() {
    const { editedTodo } = this.state;
    const { todos } = this.props;
    return (
      <ul>
        <li>{JSON.stringify(todos)}</li>
        {todos.map(todo => (
          <li key={todo.id}>
            {todo === editedTodo ? (
              <form onSubmit={this.submitTodoForm}>
                <input
                  autoFocus
                  value={editedTodo.text}
                  onChange={e => this.onChangeTodoText(e.target.value)}
                />
                &nbsp;
                <button type="submit">Save</button>
                &nbsp;
                <button type="button" onClick={this.toggleEditTodo}>
                  Cancel
                </button>
              </form>
            ) : (
              <span>
                {todo.text}
                &nbsp;
                <button onClick={() => this.toggleEditTodo(todo)}>Edit</button>
              </span>
            )}
          </li>
        ))}
      </ul>
    );
  }
}

1 个答案:

答案 0 :(得分:1)

https://codesandbox.io/s/3q1k4m3vm5

这是工作版本。

问题出在this.setState({ editedTodo: todo })上。您正在将道具中的todo副本分配给州。因此,它引用的是同一项目。确保您永远不会直接改变道具,这是一种反模式。