React navigation goback() и обновить родительское состояние
У меня есть страница, которая будет отображать имя пользователя, если он вошел в систему или "Создать учетную запись" или "Войти", если он/нет. Экран, как показано ниже
Они могут перейти на страницу "Войти" или "Создать учетную запись". После успешного входа в систему или регистрации он перейдет на эту страницу и отобразит имя пользователя. Экран, как показано ниже
В настоящее время я храню данные пользователя в AsyncStorage
, я хочу обновить это поле после успешного входа в систему или регистрации при переадресации с этой страницы.
Как я могу это достичь?
есть ли способ передать параметр из navigate.goback()
и родитель может прослушивать параметры и обновлять его состояние?
Ответы
Ответ 1
Вы можете передать функцию обратного вызова в качестве параметра, когда вы вызываете навигацию следующим образом:
const DEMO_TOKEN = await AsyncStorage.getItem('id_token');
if (DEMO_TOKEN === null) {
this.props.navigation.navigate('Login', {
onGoBack: () => this.refresh(),
});
return -3;
} else {
this.doSomething();
}
И определите свою функцию обратного вызова:
refresh() {
this.doSomething();
}
Затем в режиме регистрации/регистрации перед goBack вы можете сделать это:
await AsyncStorage.setItem('id_token', myId);
this.props.navigation.state.params.onGoBack();
this.props.navigation.goBack();
Ответ 2
Есть ли способ передать param из navigate.goback()
и родитель может прослушать params и обновить его состояние?
Вы можете передать функцию обратного вызова в качестве параметра (как упоминалось в других ответах).
Вот более ясный пример, когда вы переходите от А к В и хотите, чтобы Б передавал информацию обратно А, вы можете передать обратный вызов (здесь на onSelect
):
ViewA.js
import React from "react";
import { Button, Text, View } from "react-native";
class ViewA extends React.Component {
state = { selected: false };
onSelect = data => {
this.setState(data);
};
onPress = () => {
this.props.navigate("ViewB", { onSelect: this.onSelect });
};
render() {
return (
<View>
<Text>{this.state.selected ? "Selected" : "Not Selected"}</Text>
<Button title="Next" onPress={this.onPress} />
</View>
);
}
}
ViewB.js
import React from "react";
import { Button } from "react-native";
class ViewB extends React.Component {
goBack() {
const { navigation } = this.props;
navigation.goBack();
navigation.state.params.onSelect({ selected: true });
}
render() {
return <Button title="back" onPress={this.goBack} />;
}
}
Снимите шляпу для мусора - обратитесь к https://github.com/react-navigation/react-navigation/issues/288#issuecomment-315684617
Ответ 3
Я столкнулся с аналогичной проблемой, так вот как я решил ее, зайдя более подробно.
Первый вариант - вернуться к родительскому с параметрами, просто определите в нем функцию обратного вызова, как это в родительском компоненте:
updateData = data => {
console.log(data);
alert("come back status: " + data);
// some other stuff
};
и перейдите к ребенку:
onPress = () => {
this.props.navigation.navigate("ParentScreen", {
name: "from parent",
updateData: this.updateData
});
};
Теперь у ребенка это можно назвать:
this.props.navigation.state.params.updateData(status);
this.props.navigation.goBack();
Второй вариант. Чтобы получить данные из любого компонента, как объясняет другой ответ, AsyncStorage можно использовать либо синхронно, либо нет.
После сохранения данных его можно использовать в любом месте.
// to get
AsyncStorage.getItem("@item")
.then(item => {
item = JSON.parse(item);
this.setState({ mystate: item });
})
.done();
// to set
AsyncStorage.setItem("@item", JSON.stringify(someData));
или либо использовать функцию async, чтобы сделать ее самообновлением, когда она получает новое значение, делая так.
this.state = { item: this.dataUpdate() };
async function dataUpdate() {
try {
let item = await AsyncStorage.getItem("@item");
return item;
} catch (e) {
console.log(e.message);
}
}
Дополнительную информацию см. В документах AsyncStorage.
Ответ 4
Для тех, кто не хочет управлять через реквизит, попробуйте это. Он будет звонить каждый раз, когда эта страница появится.
Примечание * (это не только для goBack, оно будет вызываться каждый раз, когда вы заходите на эту страницу.)
import { NavigationEvents } from 'react-navigation';
render() {
return (
<View style={{ flex: 1 }}>
<NavigationEvents
onWillFocus={() => {
// Do your things here
}}
/>
</View>
);
}
Ответ 5
EDITED: лучшее решение - использовать NavigationEvents, вам не нужно создавать слушателей вручную :)
Вызывать функцию обратного вызова не рекомендуется, проверьте этот пример с помощью слушателя (не забудьте удалить все слушатели из componentWillUnMount с помощью этой опции)
Компонент А
navigateToComponentB() {
const { navigation } = this.props
this.navigationListener = navigation.addListener('willFocus', payload => {
this.navigationListener.remove()
const { state } = payload
const { params } = state
//update state with the new params
const { otherParam } = params
this.setState({ otherParam })
})
navigation.push('ComponentB', {
returnToRoute: navigation.state,
otherParam: this.state.otherParam
})
}
Компонент Б
returnToComponentA() {
const { navigation } = this.props
const { routeName, key } = navigation.getParam('returnToRoute')
navigation.navigate({ routeName, key, params: { otherParam: 123 } })
}
Для получения дополнительной информации о предыдущем примере: https://github.com/react-navigation/react-navigation/issues/288#issuecomment-378412411
С уважением, Николлс
Ответ 6
Я просто использовал стандартную навигационную функцию, указав имя маршрута ViewA и передав параметры, сделал именно то, что сделал бы goBack.
this.props.navigation.navigate("ViewA",
{
param1: value1,
param2: value2
});
Ответ 7
Если вы используете redus
вы можете создать действие для хранения данных и проверить значение в родительском Component
или вы можете использовать AsyncStorage
.
Но я думаю, что лучше передавать только JSON-serializable
параметры, потому что если когда-нибудь вы захотите сохранить состояние навигации, это будет не очень легко.
Также обратите внимание, что у react-navigation
есть эта функция в экспериментальном https://reactnavigation.org/docs/en/state-persistence.html
Каждый параметр, маршрут и состояние навигации должны быть полностью JSON-сериализуемыми, чтобы эта функция работала. Это означает, что ваши маршруты и параметры не должны содержать функций, экземпляров классов или рекурсивных структур данных.
Мне нравится эта функция в режиме разработки, и когда я передаю params как функцию, я просто не могу ее использовать