I am new to React Native. How can we refresh/reload previous screen when returning to it by calling goBack()
?
Lets say we have 3 screens A, B, C:
A -> B -> C
When we run goBack()
from screen C it goes back to screen B but with old state/data. How can we refresh it? The constructor doesn't get called 2nd time.
Yes, constructor is called only for the first time and you can't call it twice.
First: But you can separate the data getter/setter from the constructor and put it in a function, this way you can pass the function down to the next Scene and whenever you're going back you may simply recall the function.
Better: You can make a go back function in your first scene which also updates the scene while going back and pass the go back function down. This way the second scene would not be aware of your update function which is reasonable.
Best: You can use redux and dispatch a go-back action in your second scene. Then in your reducer you take care of going back & refreshing your scene.
Adding Api Call in callBack sovles the issue
componentDidMount() {
this.props.fetchData();
this.willFocusSubscription = this.props.navigation.addListener(
'willFocus',
() => {
this.props.fetchData();
}
);
}
componentWillUnmount() {
this.willFocusSubscription.remove();
}
The built in listener function which comes with React-Navigation would be the easiest solution. Whenever a component is 'focused' on a again by navigating back, the listener will fire off. By writing a loadData function that can be called both when loading the Component AND when the listener is notified, you can easily reload data when navigating back.
componentWillMount(){
this._subscribe = this.props.navigation.addListener('didFocus', () => {
this.LoadData();
//Put your Data loading function here instead of my this.LoadData()
});}
On your screen B constructor will work like magic :)
this.props.navigation.addListener(
'didFocus',
payload => {
this.setState({is_updated:true});
}
);
If you're trying to get new data into a previous view, and it isn't working, you may want to revisit the way you're piping data into that view to begin with. Calling goBack
shouldn't effect the mounting of a previous component, and likely won't call its constructor again as you've noted.
As a first step, I would ask if you're using a Component, PureComponent, or Functional Component. Based on your constructor comment it sounds like you're extending a Component class.
If you're using a component, the render method is subject to shouldComponentUpdate and the value of your state is in your control.
I would recommend using componentWillReceiveProps to validate the component is receiving the new data, and ensuring its state has been updated to reflect the new data.
If you're using the constructor to call an API or async function of some kind, consider moving that function into a parent component of both the route you're calling goBack
from and the component you're wanting to update with the most recent data. Then you can ask your parent component to re-query the API, or update its state from a child component.
If Route C updates the "state/data" of the application, that update should be propagated to a shared parent of routes A, B and C, and then passsed down as a prop.
Alternatively, you can use a state management solution like Redux to maintain that state independent of parent/child components - you would wrap your components in a connect
higher-order component to get the latest updates any time the application state changes.
TL;DR Ultimately it sounds like the answer to your question is rooted in where your application state is being stored. It should be stored high enough in your component hierarchy that each route always receives the latest data as a prop, passed from its parent.
This answer assumes that the react-native-navigation library is being used, which is unlikely because it doesn't actually have a goBack() method...
The constructor doesn't call a second time because screen A and B are still rendered (but hidden behind screen C). If you need to know when screen B is going to be visible again you can listen to navigation events.
class ScreenB extends Component {
constructor(props) {
super(props);
// Listen to all events for screen B
this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
}
onNavigatorEvent = event => {
switch (event.id) {
case 'willAppear':
// refresh your state...
break;
};
}
Other events: willDisappear
, didAppear
, didDisappear
An alternate solution to your problem is to use a state management solution like Redux to provide the state to all screens whenever it is updated (rather than just on screen transitions. See old react-native-nav/redux example.
None of this answers worked for me sadly, but I've found a simple library, it does the same work:
npm install --save react-native-event-listeners
componentDidMount() {
this.listener = EventRegister.addEventListener('reloadData', (data) => {
console.log("data is fetched");
this.updateState(data); // private function that update the state using setState to trigger render
});
}
componentWillUnmount() {
EventRegister.removeEventListener(this.listener)
}
And in other component, in my case an opacity button:
<TouchableOpacity
onPress={() => {
fetch('url').then(data => {
ServiceLocator.saveData('matba', data);
EventRegister.emit('reloadData', data);
props.nav.goBack()
})
.catch(error =>{
console.log(error);
Alert.alert("Cannot connect to the server");
props.nav.goBack()
});
}}
>
来源:https://stackoverflow.com/questions/46504660/refresh-previous-screen-on-goback