Ukasha
Ukasha

Reputation: 2334

Why changing state (props based) in child component can effect the props?

You can see demo here. Try to click "Edit" button and change the value of input field.

In the parent component, it pass an array of objects to its child. Inside the child component, one of objects can be passed into its state, named editedTodo. But, strangely, the prop is changed when editedTodo is changed.

This is not what I want. Anyone can help me solve this?

Here is the todo Component:

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

Upvotes: 1

Views: 65

Answers (1)

leogoesger
leogoesger

Reputation: 3830

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

Here is the working version.

The problem was with this.setState({ editedTodo: todo }). You are assigning the same copy of todo from the props to the state. So it is referencing the same item. Make sure you are never mutating your props directly, it is an anti-pattern.

Upvotes: 1

Related Questions