react-three-renderer
react-three-renderer copied to clipboard
r3r appears to fire react lifecycle methods out of expected order
PROBLEM
It appears that r3r renders components in an unexpected order, firing React lifecycle hook methods in an unexpected order. Right now this is what I believe I'm seeing:
- Parent
renderis called - Parent
componentDidUpdateis called - Child
componentWillReceivePropsis called - Child
renderis called
This is the order I expect:
- Parent
renderis called - Child
componentWillReceivePropsis called - Child
renderis called - Parent
componentDidUpdateis called
I'm not 100% sure about the order of willReceiveProps with regards to children, but I believe that the parent componentDidUpdate firing before the child render completes is an error.
HOW TO REPRODUCE
- Clone my fork of the examples
npm installnpm run serve- Open http://localhost:8080/
- Click on the "Simple" example on the sidebar
- Open the Javascrit debugger in your browser
- Run
window.debuggg = true - Note the order of the logs:
wrapper render
index.js componentDidUpdate called
Cube.js componentWillReceiveProps
Cube.js render
This is a crude repro case but I think it demonstrates the problem. I've modified the "Simple" example to have a child object called Cube.js. I've added lines such as this one:
if( window.debuggg ) {
console.log('index.js wrapper render');
}
...at 4 points throughout the code. Only when the child Cube.js renders is the debug flag turned off:
if( window.debuggg ) {
window.debuggg = false;
console.log('Cube.js render');
}
You can see in the order of what's printed (copied above), it appears that the component in Simple/index.js renders, then its componentDidUpdate is fires, then after that Cube.jss debugging starts. This appears to be out of order compared to what I would expect from the component lifecycle. As far as I understand it a parent's componentDidUpdate doesn't fire unless all of this children have finished rendering.
Maybe this is related?
https://github.com/toxicFork/react-three-renderer/blob/staging/2.1/src/lib/React3.js#L71-L73
componentDidUpdate() {
this._render();
}
Child components aren't rendered until after the parent component has updated?
Thanks for the report :)
For that component yes, I can make that render happen earlier, I will now be looking at the provided test as well to see if it is the same issue or do I need to fix something further in the internals
@DelvarWorld does this happen for components deeper inside <React3> as well, or only for the root?
The reason for doing the internal rendering within componentDidUpdate is that updating some properties in the <canvas/> clears it. For example if you rendered something into a canvas and then change its width, it will be blank.
When the canvas element is created, and subsequently whenever the width and height attributes are set (whether to a new value or to the previous value), the bitmap and any associated contexts must be cleared back to their initial state and reinitialized with the newly specified coordinate space dimensions.
So we need to render after react-dom action is complete for at least the canvas.
Technical notes
Potential fix thoughts: render a <div/> for React3#render and within componentWillUpdate:
- if it's possible to nest
react-domrender calls:- use
react-domto manually render the canvas into the div and then immediately render into the canvas beforecomponentWillUpdateeven finishes
- use
- otherwise:
- create a new internal
<canvas/>component forreact-three-rendererto render
- create a new internal
I will try these in order.
Alright, option 1 works!
Linking http://stackoverflow.com/questions/39626921/react-three-renderer-refs-not-current-in-componentdidupdate-mvce-included
Converting to bug as well to increase priority