我有一个页面,如果他/她已登录,将显示用户名;如果未登录,则显示“创建帐户”或“登录”选项。屏幕如下
他们可以导航到“登录”或“创建帐户”页面。成功登录或注册后,它将导航到此页面,并显示用户名。屏幕如下
目前,我将用户数据存储在中AsyncStorage
,我希望在用户成功登录或从页面重定向时注册后更新此字段。
我该如何实现?
有没有一种方法可以从中传递参数,navigate.goBack()
并且父级可以听这些参数并更新其状态?
Answers:
您可以像下面这样调用Navigation时将回调函数作为参数传递:
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();
React Navigation v5的更新:
await AsyncStorage.setItem('id_token', myId);
this.props.route.params.onGoBack();
this.props.navigation.goBack();
onGoBack: this.refresh
,而不是onGoBack: () => this.refresh()
useEffect(refresh, [route.params?.updateTime])
,而子级可以执行.navigate("parent", {updateTime: new Date().getTime()})
。
有没有一种方法可以从中传递参数,
navigate.goback()
并且父级可以听这些参数并更新其状态?
您可以将回调函数作为参数传递(如其他答案中所述)。
这是一个更清晰的示例,当您从A导航到B并希望B将信息传递回A时,您可以传递一个回调(在此处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
对于React Navigation v5
ViewB.js
import React from "react";
import { Button } from "react-native";
class ViewB extends React.Component {
goBack() {
const { navigation, route } = this.props;
navigation.goBack();
route.params.onSelect({ selected: true });
}
render() {
return <Button title="back" onPress={this.goBack} />;
}
}
undefined is not an object (evaluating navigation.state.params.onSelect)
不是函数,
this.props.route.params.onSelect
bind(this)
才能this.setState()
工作。所以onPress = () => { this.props.navigate("ViewB", { onSelect: this.onSelect.bind(this) }); };
对于那些不想通过道具进行管理的人,请尝试此操作。出现此页面时,它将每次调用。
注意*(这不仅适用于goBack,而且每次您进入此页面时都会调用。)
import { NavigationEvents } from 'react-navigation';
render() {
return (
<View style={{ flex: 1 }}>
<NavigationEvents
onWillFocus={() => {
// Do your things here
}}
/>
</View>
);
}
我面临着类似的问题,因此这是我通过进一步研究细节来解决的方法。
选项一是使用参数导航回到父级,只需在父级组件中像这样定义回调函数:
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));
或者使用异步函数使其在获得新值时进行自我更新,就像这样。
this.state = { item: this.dataUpdate() };
async function dataUpdate() {
try {
let item = await AsyncStorage.getItem("@item");
return item;
} catch (e) {
console.log(e.message);
}
}
有关更多详细信息,请参见AsyncStorage文档。
编辑: 最好的解决方案是使用NavigationEvents,您不需要手动创建侦听器:)
不强烈建议调用回调函数,请使用侦听器检查此示例(请记住使用此选项从componentWillUnMount中删除所有侦听器)
成分A
navigateToComponentB() {
const { navigation } = this.props
this.navigationListener = navigation.addListener('willFocus', payload => {
this.removeNavigationListener()
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
})
}
removeNavigationListener() {
if (this.navigationListener) {
this.navigationListener.remove()
this.navigationListener = null
}
}
componentWillUnmount() {
this.removeNavigationListener()
}
部件B
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
问候,尼科尔斯
我只是使用了标准的导航功能,即提供了ViewA路由名称并传递了参数,正是goBack会做的。
this.props.navigation.navigate("ViewA",
{
param1: value1,
param2: value2
});
goBack()
。这将前进到上一个视图(它正在添加到堆栈中)。而且,我认为这不能回答问题。
this.props.navigation.navigate
是与调用goBack()
。测试一下,您将看到。屏幕动画从左到右滑动。
navigation.navigate
总是导致路由被推入堆栈。
如果您正在使用redus
,则可以创建一个操作来存储数据并检查父项中的值,Component
或者可以使用AsyncStorage
。
但是我认为最好只传递JSON-serializable
参数,因为如果有一天您想保存导航状态,这并不是一件容易的事。
另请注意react-navigation
,实验性https://reactnavigation.org/docs/en/state-persistence.html中具有此功能
每个参数,路线和导航状态都必须完全JSON可序列化才能使用此功能。这意味着您的路由和参数不得包含任何函数,类实例或递归数据结构。
我喜欢在开发模式下使用此功能,当我将参数作为函数传递时,我简直无法使用它
第一屏
updateData=(data)=>{
console.log('Selected data',data)
}
this.props.navigation.navigate('FirstScreen',{updateData:this.updateData.bind(this)})
第二屏
// use this method to call FirstScreen method
execBack(param) {
this.props.navigation.state.params.updateData(param);
this.props.navigation.goBack();
}
对于React Navigation v5,只需使用navigation方法。从文档:
为此,可以使用Navigation方法,如果屏幕已经存在,则该方法的作用类似于goBack。您可以通过导航传递参数以将数据传递回
完整示例:
import React from 'react';
import { StyleSheet, Button, Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
const Stack = createStackNavigator();
function ScreenA ({ navigation, route }) {
const { params } = route;
return (
<View style={styles.container}>
<Text>Params: {JSON.stringify(params)}</Text>
<Button title='Go to B' onPress={() => navigation.navigate('B')} />
</View>
);
}
function ScreenB ({ navigation }) {
return (
<View style={styles.container}>
<Button title='Go to A'
onPress={() => {
navigation.navigate('A', { data: 'Something' })
}}
/>
</View>
);
}
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator mode="modal">
<Stack.Screen name="A" component={ScreenA} />
<Stack.Screen name="B" component={ScreenB} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
static navigationOptions = ({navigation}) => ({ headerRight: <Button title="test" onPress={() => navigation.navigate('GoToScreen', {onGoBack: () => this.refresh()})} /> });
它,那会很烦this.refresh()
。有什么办法吗?