Обновить предыдущий экран в goBack()
Я новичок в React Native. Как мы можем обновить/перезагрузить предыдущий экран, вернувшись к нему, вызывая goBack()
?
Допустим, у нас есть 3 экрана A, B, C:
A -> B -> C
Когда мы запускаем goBack()
с экрана C, он возвращается на экран B, но со старым состоянием/данными. Как мы можем его обновить? Конструктор не называется 2-й раз.
Ответы
Ответ 1
Да, конструктор вызывается только в первый раз, и вы не можете назвать его дважды.
Во-первых: Но вы можете отделить получатель/сеттер данных от конструктора и поместить его в функцию, таким образом вы можете передать функцию до следующей сцены, и всякий раз, когда вы возвращаетесь, вы можете просто вызвать функцию.
Лучше: вы можете вернуться в свою первую сцену, которая также обновляет сцену, возвращаясь назад и передавая назад функцию вниз. Таким образом, вторая сцена не будет знать о вашей функции обновления, которая является разумной.
Лучшее: вы можете использовать сокращение и отправить действие назад во второй сцене. Затем в вашем редукторе вы позаботитесь о возврате и освежении своей сцены.
Ответ 2
Добавление Api Call в callBack решает проблему
componentDidMount() {
this.props.fetchData();
this.willFocusSubscription = this.props.navigation.addListener(
'willFocus',
() => {
this.props.fetchData();
}
);
}
componentWillUnmount() {
this.willFocusSubscription.remove();
}
Ответ 3
Встроенная функция слушателя, которая поставляется с React-Navigation, будет самым простым решением. Всякий раз, когда компонент снова "фокусируется" на элементе навигации, слушатель срабатывает. Написав функцию loadData, которую можно вызывать как при загрузке компонента, так и при получении уведомления от слушателя, вы можете легко перезагрузить данные при переходе назад.
componentWillMount(){
this._subscribe = this.props.navigation.addListener('didFocus', () => {
this.LoadData();
//Put your Data loading function here instead of my this.LoadData()
});}
Ответ 4
На вашем экране B конструктор будет работать как по волшебству :)
this.props.navigation.addListener(
'didFocus',
payload => {
this.setState({is_updated:true});
}
);
Ответ 5
Если вы пытаетесь получить новые данные в предыдущем представлении, и он не работает, вы можете вернуться к тому, чтобы начать с того, как вы отправляете данные в эту точку зрения. Вызов goBack
не должен влиять на установку предыдущего компонента и, скорее всего, не вызовет его конструктор, как вы уже отметили.
В качестве первого шага я бы спросил, используете ли вы компонент, компонент PureComponent или функциональный компонент. На основе вашего комментария конструктора звучит так, будто вы расширяете класс Component.
Если вы используете компонент, метод рендеринга подчиняется shouldComponentUpdate, и значение вашего состояния находится под вашим контролем.
Я бы рекомендовал использовать componentWillReceiveProps для проверки того, что компонент получает новые данные, и обеспечение его состояния обновлено, чтобы отразить новые данные.
Если вы используете конструктор для вызова какой-либо функции API или async, подумайте о том, чтобы переместить эту функцию в родительский компонент как маршрута, который вы вызываете goBack
и компонента, который вы хотите обновить, с помощью последних данных, Затем вы можете попросить своего родительского компонента повторно запросить API или обновить его состояние из дочернего компонента.
Если Route C обновляет "состояние/данные" приложения, это обновление должно распространяться на общего родителя маршрутов A, B и C, а затем передаваться в качестве опоры.
В качестве альтернативы вы можете использовать решение управления состоянием, такое как Redux, чтобы поддерживать это состояние независимо от родительских/дочерних компонентов - вы должны были бы обернуть ваши компоненты в компонент более высокого уровня connect
, чтобы получать последние обновления в любое время, когда изменяется состояние приложения.
TL; DR В конечном итоге это звучит так, как будто ответ на ваш вопрос основан на том, где хранится ваше состояние приложения. Он должен храниться достаточно высоко в вашей иерархии компонентов, чтобы каждый маршрут всегда получал последние данные в качестве опоры, переданные от своего родителя.
Ответ 6
В этом ответе предполагается, что используется библиотека реагирования-натуральной навигации, что маловероятно, потому что на самом деле у нее нет метода goBack()...
Конструктор не вызывает второй раз, потому что экран A и B все еще отображаются (но скрыты за экраном C). Если вам нужно знать, когда экран B снова будет виден, вы можете прослушивать события навигации.
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;
};
}
Другие события: willDisappear
, didAppear
, didDisappear
Альтернативное решение вашей проблемы заключается в использовании решения управления состоянием, такого как Redux, для предоставления состояния всем экранам всякий раз, когда он обновляется (а не только на переходах на экране). См. Пример old response-native-nav/redux.
Ответ 7
Ни один из этих ответов не сработал для меня, к сожалению, но я нашел простую библиотеку, она выполняет ту же работу:
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)
}
И в другом компоненте, в моем случае кнопка непрозрачности:
<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()
});
}}
>