0

When "Reset" is clicked, I want to make the page the first appearance. When I click "Reset" first, it resets to the first appearance. However, when I change the obj1 state again and click "Reset", it won't be back. Instead, the obj1 is referenced.

My question is,

  1. What's wrong with the "handleReset" function? Why can't it be updated by obj2?
  2. Instead of using window.location.reload(), how can I make the page the first state that nothing hasn't changed? I was thinking of keeping obj1 in variable somewhere and when handleReset is called, it could feed the obj1 state. But I'm not sure how to realize that..
  3. I'm using React Developer Tools but Uncaught Error happens. What's causing it?

*First appearance that obj1.id and obj1.num are displayed. enter image description here

*When I change the obj1 state again and click "Reset", it won't be back. Instead, the obj1 is referenced. enter image description here

*Uncaught Error: Cannot add node "1" because a node with that id is already in the Store. enter image description here

App class(Parent)

class App extends Component {
  state = {
    obj1: [
      { id: 1, num: 0 },
      { id: 2, num: 1 },
      { id: 3, num: 2 },
    ],
    obj2: [
      { id: 1, num: 0 },
      { id: 2, num: 1 },
      { id: 3, num: 2 },
    ],
  };

  handleReset = () => {
    const obj2 = [...this.state.obj2];
    this.setState({ obj1: obj2 });
  };

  handleDelete = (id) => {
    console.log("id", id);
    const obj1 = this.state.obj1.filter((obj) => obj.id !== id);
    this.setState({ obj1 });
  };

  handleIncrement = (counter) => {
    const temState = [...this.state.obj1];
    temState[counter - 1].num++;
    this.setState({ obj1: [...temState] });
  };

  render() {
    return (
      <div>
        <Counters
          obj1={this.state.obj1}
          onReset={this.handleReset}
          onHandleDelete={this.handleDelete}
          onHandleIncrement={this.handleIncrement}
        />
      </div>
    );
  }
}

Counters class(child of App class)

class Counters extends Component {
  render() {
    return (
      <div>
        <span onClick={this.props.onReset} className="badge bg-primary m-2">
          Reset
        </span>
        {this.props.obj1.map((obj) => (
          <Counter
            key={obj.id}
            //props
            handleIncrement={this.props.onHandleIncrement}
            handleDelete={this.props.onHandleDelete}
            counter={obj}
          />
        ))}
      </div>
    );
  }
}

Counter class (controlled by Counters class)

class Counter extends Component {
  render() {
    return (
      <div>
        <span className="badge bg-primary">{this.props.counter.num}</span>
        <button
          onClick={() => this.props.handleIncrement(this.props.counter.id)}
          className="badge bg-secondary m-2 "
        >
          BUTTON
        </button>
        <span
          onClick={() => this.props.handleDelete(this.props.counter.id)}
          className="badge bg-danger m-2"
        >
          DELETE
        </span>
      </div>
    );
  }
}
jimi1206
  • 1
  • 3

1 Answers1

0

The issue is how you copy properties of obj2 into obj1 in handleReset. This link explains how to copy an array of objects How do you clone an Array of Objects in Javascript?

What you would need to do is also copy objects inside obj2. See snippet below:

  handleReset = () => {
    const { obj2 } = this.state;
    const obj1 = obj2.map((item) => ({ ...item }));
    this.setState({ obj1 });
 };

Check working snippet https://codesandbox.io/s/sleepy-dew-6sp8k Also, I am not able to reproduce the error you are facing. Things seem to be working well.

cdoshi
  • 2,772
  • 1
  • 13
  • 20
  • 1
    Thank you for the snippet! Now I can make the page the first condition, which I wanted to do. Also, if I use the map in constructor, I can remove obj2, which makes the code cleaner. constructor() { super(); const { obj1 } = this.state; this.objClone = obj1.map((item) => ({ ...item })); } Regarding the error, my React version is 17.0.2 and it might be related. – jimi1206 May 16 '21 at 06:14