When does a react constructor get called on a component? Because mine is getting called only once

Viewed 200

Must be some fundamental wrong-headedness with my understanding. I have a react native app that is supposed to display multiple modal popups which I have implemented as a stack of render functions.

render() {
    if (this.state.popupStack.length > 0) {
         return this.state.popupStack[0]()   
    } else {
         return null
    }
}

For instance to display something on the stack, I do this:

this.state.popupStack.push( () => <SomeComponent thing={propA} /> )
this.state.popupStack.push( () => <SomeComponent thing={propB} /> )

And it works fine, I can push all sorts of things onto the stack and shift them out and the next thing renders.

The issue occurs if the components (not functional elements) need state which I initialize in their constructors. The first time I use SomeComponent in this way, the constructor is called and all is good. But if I push the same component again, the component is rendered according to the changed props, but the constructor isn't called. React figures the component is mounted and is happy to pass new props in, but it messes things up because it is using the previous components state. The 2nd render function pushed on the stack is using the same instance of SomeComponent. I dont want that.

Does this makes sense?

I figured it would call the constructor every time...

What's my malfunction :)

Thanks very much

3 Answers

Constructor would be called only once. Here is the lifecycle cheatsheet for react. Only render and other lifecyle hooks are called with each update. You may want to use props instead of local state if you want SomeComponent to always have updated values from parent component

The clue was that React knows these are different instances

render() {
    <SomeComponent/>
    <SomeComponent/>
}

because even though they are the same type of component, there are clearly two of them.

but react doesnt know if there is only a single render function called that has the same Component type returned by it. As far as its concerned, there is only one component and it is the same type of component each time, so its the same component.

The way React keeps tack of these things is with 'key'. The following code does what I want (instantiates a different component each time)

this.state.popupStack.push( () => <SomeComponent key = '1' thing={propA} /> )
this.state.popupStack.push( () => <SomeComponent key = '2' thing={propB} /> )

The usual nature in mobile apps unlink webapps, when pages/screens are loaded once on view they are pushed to the stack and maintained in memory for back navigation, forward navigations etc. So there is no need to invoke the constructor to re-initialize the memory for the component. The best way is to either use getDerivedStateFromProps, but it executes on all screens, even if the screen is not visible on the view port.

It will be flexible if you check the current modal is in the viewport, and handle the action, like below post. component-viewport

Related