0

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

Ahmed Hosny
  • 370
  • 4
  • 16

2 Answers2

1

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).
Alex Rintt
  • 1,618
  • 1
  • 11
  • 18
  • but the class comes form a library and cant be guaranteed creating new instance of it be exactly like the one the one that it gives me from an static method of it that i call, so new Room() is out of option :( – shahrooz bazrafshan Aug 11 '22 at 18:26
  • unfortunately I can't tell a solution only by using these infos, may you want to explain better in a new question or update the current one. Try to explain these constraints better (why can't you create a new class instance, even if it's from another library). – Alex Rintt Aug 11 '22 at 18:50
0

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} won't clone the prototype.

halfer
  • 19,824
  • 17
  • 99
  • 186
Alen.Toma
  • 4,684
  • 2
  • 14
  • 31