Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what happens in react when setState with object instance of a class

I have this fiddle

let m = new Mine();
this.setState(m, () => {
    console.log('1:', m instanceof Mine, m.x, m.meth);
    // => 1: true 123 function meth() {}
    console.log('2:', this.state instanceof Mine, this.state.x, this.state.meth);
    // => 2: false 123 undefined
});

As you can see I create an instance of the Mine class and then set state in a react component with that instance.

I would expect this.state to contain exactly that instance but while the instance properties that are set in the constructor are available I can't access any of the class methods on that instance.

The test in the fiddle shows that this.state is not an instance of the class Mine.

Does anybody understand what is going on or is this unintended behavior?

like image 220
Vlad Avatar asked Jul 20 '16 09:07

Vlad


People also ask

Does setState trigger componentDidMount?

You can call setState() immediately in componentDidMount() and triggers an extra rendering, but this happens before the browser updates the screen, calling render() twice.

What happens on setState React?

The setState() method enqueues all of the updates made to the component state and instructs React to re-render the component and its children with the updated state.

What will happen if you use setState () in constructor?

What will happen if you use setState() in constructor? When you use setState() , then apart from assigning to the object state React also re-renders the component and all its children. You would get error like this: Can only update a mounted or mounting component.

Can you use setState in class component?

To update state , React developers use a special method called setState that is inherited from the base Component class. The setState method can take either an object or a function as the first argument.


1 Answers

After more investigation I found out the reason why that happens.

The function _processPendingState from react uses Object.assign to set the new state, so since the target object is a new object (different than what is passed to setState) the new state loses the quality of being an instance of the "Mine" class.

And because Object.assign only copies own enumerable properties from the sources to the target the new state also won't have the class methods.

If in the fiddle we replace the line...

let m = new Mine();

with...

let m = {x: 123};
Object.defineProperty(m, 'meth', {
    enumerable: false,
    get() { return function() {}; }
});

we still don't have the "meth" property on the resulting state. Even if "m" owns the "meth" property it is not enumerable.

like image 112
Vlad Avatar answered Oct 01 '22 06:10

Vlad