Home > database >  mutating react state delete class method
mutating react state delete class method

Time:08-12

I have a class instance in my react state and it's like below:

class Room {
  name;
  participant;
  constructor(name) {
    this.name = name;
    this.participant = {
      screensharing: false,
    };
  }
  sendReinvite() {
    console.log("reinvite");
  }
}

after changing screen share and using the spread operator for mutating state, sendReinvite method is deleted and causes an error in the second click:

const SpreadOperator = () => {
  const [room, changeRoom] = useState(new Room());

  const toggleScreenSharing = () => {
    console.log("room", room);
    room.participant.screensharing = !room.participant.screensharing;
    room.sendReinvite();
    changeRoom({...room});
  };
  return (
    <div>
      <h1>spread operator</h1>
      <button onClick={toggleScreenSharing}>Screen share</button>
    </div>
  );
};
export default SpreadOperator;

error: Uncaught TypeError: room.sendReinvite is not a function how can I change screen share without losing methods, by the way, that instance comes from some library and I can't change that,

check this like for a real one:

room

CodePudding user response:

Do not use spread operator in class instances

Check this link to see Why can I not use the spread operator on a class function?

Consider the following snippet:

class A {
  constructor() {
    this.a = 'a', this.b = 'b'
  }
  mymethod() { 
    return true 
  }
}

If you do:

const a = new A();
a.mymethod(); // true

And if you use spread operator in it:

const a = new A();
const b = { ...a };
b.mymethod(); // b.mymethod is not a function
b.a; // 'a'

Do not modify your state directly

Again, Why can't I directly modify a component's state, really?

You do it in:

room.participant.screensharing = !room.participant.screensharing;

So, replace:

room.participant.screensharing = !room.participant.screensharing;
room.sendReinvite();
changeRoom({...room});

with:

const myNewRoomState = new Room(); // Create another state object
myNewRoomState.participant.screensharing = !room.participant.screensharing;
myNewRoomState.sendReinvite();
changeRoom(myNewRoomState);

This is still doubtful because you are using a mutable class instance to store your immutable state, I recommend you to check this post: Is there a react way to store a mutable class instance objects in state?

But in summary:

  • Avoid spread operator in class instances.
  • Do not modify your state directly, change it's properties through changeRoom function (which is the function responsible for changing your room state).

CodePudding user response:

Alex did a good job answering this, but I want to add something to help you understand more.

sendReinvite exist in Room.prototype and doing {...rom} wont clone the prototype.

  • Related