我有一个页面,如果他/她已登录,则会呈现用户的姓名,或者"创建帐户"或者"登录"如果他/她没有选择。屏幕如下
他们可以导航到"登录"或"创建一个帐户"页。成功登录或注册后,它将导航到此页面,并显示用户名。屏幕如下
目前,我将用户数据存储在AsyncStorage
中,我想在用户成功登录后更新此字段,或者在从页面重定向时注册。
我怎样才能做到这一点?
有没有办法从navigate.goback()
传递参数,父母可以听取参数并更新其状态?
答案 0 :(得分:50)
当您调用如下导航时,您可以将回调函数作为参数传递:
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();
答案 1 :(得分:20)
有没有办法从
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} />;
}
}
为debrice致敬 - 请参阅https://github.com/react-navigation/react-navigation/issues/288#issuecomment-315684617
答案 2 :(得分:11)
我遇到了类似的问题,所以这就是我如何通过更多细节来解决它。
选项一是使用参数导航回父级,只需在其中定义一个回调函数,就像在父组件中一样:
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 docs。
答案 3 :(得分:7)
对于那些不想通过道具进行管理的人,请尝试此操作。此页面出现时,它将每次调用。
注意*(这不仅适用于goBack,还会在您每次 输入此页面。)
import { NavigationEvents } from 'react-navigation';
render() {
return (
<View style={{ flex: 1 }}>
<NavigationEvents
onWillFocus={() => {
// Do your things here
}}
/>
</View>
);
}
答案 4 :(得分:2)
已编辑: 最好的解决方案是使用NavigationEvents,您无需手动创建监听器:)
不强烈建议调用回调函数,请使用侦听器检查此示例(请记住,使用此选项从componentWillUnMount中删除所有侦听器)
组件A
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
})
}
组件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
关于Nicholls
答案 5 :(得分:1)
我只是使用了标准的导航功能,即提供了ViewA路由名称并传递了参数,正是goBack会做的。
this.props.navigation.navigate("ViewA",
{
param1: value1,
param2: value2
});
答案 6 :(得分:1)
这个解决方案为我做了,根据导航网站:https://reactnavigation.org/docs/function-after-focusing-screen/#re-rendering-screen-with-the-useisfocused-hook
import { useFocusEffect } from '@react-navigation/native';
useFocusEffect(
React.useCallback(() => {
// YOUR CODE WHEN IT IS FOCUSED
return // YOUR CODE WHEN IT'S UNFOCUSED
}, [userId])
);
答案 7 :(得分:0)
如果您使用的是redus
,则可以创建一个操作来存储数据并检查父项Component
中的值,也可以使用AsyncStorage
。
但是我认为最好只传递JSON-serializable
参数,因为如果有一天您想保存导航状态,那不是很容易。
还请注意react-navigation
在实验中具有此功能
https://reactnavigation.org/docs/en/state-persistence.html
每个参数,路线和导航状态必须完整 JSON可序列化,此功能才能正常工作。这意味着您 路由和参数不得包含任何函数,类实例或 递归数据结构。
我喜欢在开发模式中使用此功能,当我将参数作为函数传递时,我简直无法使用
答案 8 :(得分:0)
第一个屏幕
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();
}
答案 9 :(得分:0)
我还将使用navigation.navigate。如果有人遇到相同的问题,并且还使用了嵌套导航器,则它的工作方式如下:
onPress={() =>
navigation.navigate('MyStackScreen', {
// Passing params to NESTED navigator screen:
screen: 'goToScreenA',
params: { Data: data.item },
})
}
答案 10 :(得分:0)
在React Navigation v5中,只需使用navigation方法。来自docs:
要实现此目的,您可以使用导航方法,其作用类似于 如果屏幕已经存在,请返回。您可以通过传递参数 导航以将数据传回
完整示例:
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',
},
});
答案 11 :(得分:0)
渲染所需组件的最简单方法是使用 useIsFocused 钩子。
React Navigation 提供了一个钩子,它返回一个布尔值,指示屏幕是否聚焦。当我们的组件不再聚焦时,钩子将在屏幕聚焦时返回 true 和 false。
首先在您要返回的所需页面中导入它。
import { useIsFocused } from '@react-navigation/native';
然后,将其存储在任何变量中,并使用 React useEffect 钩子呈现组件更改。
查看下面的代码或访问:Here
import React, { useState } from 'react';
import { useIsFocused } from '@react-navigation/core';
const HomeScreen = () => {
const isFocused = useIsFocused();
useEffect(()=>{
console.log("Focused: ", isFocused); //called whenever isFocused changes
}, [isFocused]);
return (
<View>
<Text> This is home screen! </Text>
</View>
)
}
export default HomeScreen;