Hey.
I've building an app where we have loading screen which when transits to login/home etc.
But how to I can replace first route in stack (to be able to use popToTop etc) after animation is ended?
componentDidMount runs just at the moment animation is started - which is working but basically prevents an animation.timeout works but it's dirty.onDidFocus is navigator level, not per route level.What I did was patch in #1154, then get the scene component's ref in onItemRef(ref, index, route) and add it as a field of my route object, and then in onDidFocus I called route.sceneRef.componentDidMount?().
i'll try this way, thx.
but still - some tightly coupling don't you think?
i guess so - high cohesion between related pieces
@ide
componentDidFocus?type Route = {
sceneRef?: ReactComponent;
};
<Navigator
onItemRef={(ref, index, route) => {
route.sceneRef = ref;
}}
onDidFocus={(route) => {
route.sceneRef.componentDidFocus();
}}
/>
@ide
Thank you very much, everything is working. Only problem here is scenereRef being renderScene component, not actually component of the route which forces to proxy this kind of events down the refs chain. Not very clean but way better than any other solution i could think of without much of a pain.
i'll close this issue and paste some code for any future references:
navigator component
<Navigator
ref="nav"
style={styles.container}
configureScene={this.sceneConfig}
renderScene={this.renderScene}
onItemRef={function(ref, index, route) {
route.sceneRef = ref;
}
}
onDidFocus={
function(route) {
route.sceneRef.sceneDidFocus();
}
}
initialRoute={{
...
}}
/>
renderScene
renderScene(route, navigator) {
return (
<AppScene
component={route.component}
navBar={route.navigationBar}
navigator={navigator}
route={route}
/>
);
},
AppScene.js
var Scene = React.createClass({
sceneWillFocus: function() {
var component = this.refs.component;
// do any checks needed here
component.componentWillFocus();
},
sceneDidFocus: function() {
var component = this.refs.component;
// do any checks needed here
component.componentDidFocus();
},
render: function() {
var Component = this.props.component;
var navBar = this.props.navBar;
return (
<View style={styles.scene} ref="scene">
{navBar}
<Component {...this.props} ref="component"/>
</View>
);
}
});
This will allow to use Will/DidFocus callbacks defined on component level;
But still we will need better "navigator view" handling:
But i believe it is whole other issue.
I agree there needs to be a better way of sending the "componentDidFocus" signal down the component hierarchy. This is especially important when you have nested Navigators, which the solution I offered does not solve.
Using refs to solve this is coupled code which is generally considered bad practice.
Best way IMO to solve this is by using an event bus which will notify any interested party. In this example I used our own EventBus class, but any will do.
onDidFocus(){
EventBus.ref().emit('NAVIGATOR_TRANSITION_END')
}
render() {
return (
<Navigator
...
onDidFocus={ this.onDidFocus }
/>
)
}
And in the component:
componentWillMount() {
EventBus.ref().addListener('NAVIGATOR_TRANSITION_END', this.onFocus, this)
}
Dear @PierBover, Your solution looks pretty awesome!馃憤
But I can't find any docs about EventBus, How can I use this in my project.
Thanks @h2oiswater !
EventBus is a class we have developed in house, so you won't find any documentation on it.
You could use actions with Redux, or any other event bus library such as PubSubJS, EventBus (not the one we are using), or make your own.
If you're going to use the EventBus the above code has a memory leak. You need 'removeListener' as well.
If you're going to use the EventBus the above code has a memory leak. You need 'removeListener' as well.
Obviously. That code only served for illustrative purposes.
It's not obvious to newbie programmers.
Never assume people know everything.
Memory leaks can kill projects and they are hard to debug.
Memory leaks can kill projects and they are hard to debug.
That's true. I should have probably also included a guide about design patterns and good practices with my example.
For anyone else reading, make sure to include (For example)
componentWillUnmount() {
EventBus.ref().RemoveListener('NAVIGATOR_TRANSITION_END', null, this)
}
When using any sort of event driven library.
InteractionManager might be what you're looking for and does anyone else still prefer deprecated Navigator over the other nav libraries?
https://github.com/facebook/react-native/issues/2313#issuecomment-269448381
Most helpful comment
Using refs to solve this is coupled code which is generally considered bad practice.
Best way IMO to solve this is by using an event bus which will notify any interested party. In this example I used our own
EventBusclass, but any will do.And in the component: