我有一个TabNavigator,每个标签中都有一个StackNavigator。在StackNavigator里面,我有屏幕。每个标签中的屏幕不会直接相互调用; TabNavigator在按下选项卡时处理屏幕更改。
在第一个标签中,如果用户点击按钮,则会创建一些数据。如果用户然后导航到第二个选项卡,我想将此数据传递到第二个选项卡中的屏幕。
以下是代码演示:
import React from 'react';
import { Button, Text, View } from 'react-native';
import {
createBottomTabNavigator,
createStackNavigator,
} from 'react-navigation';
class HomeScreen extends React.Component {
doIt = () => {
this.props.navigation.setParams({results: ['one', 'two']}); // <--- set data when user clicks button.
}
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
{/* other code from before here */}
<Button
title="Set Results"
onPress={this.doIt}
/>
</View>
);
}
}
class SettingsScreen extends React.Component {
render() {
console.log(this.props.navigation); // <--- console out when user clicks on this tab
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings</Text>
</View>
);
}
}
const HomeStack = createStackNavigator({
Home: HomeScreen,
});
const SettingsStack = createStackNavigator({
Settings: SettingsScreen,
});
export default createBottomTabNavigator(
{
Home: HomeStack,
Settings: SettingsStack,
},
{
}
);
this.props.navigation.state.params
永远不会在第二个标签中获取数据results
。它甚至没有密钥,所以如果我尝试访问this.props.navigation.state.params.results
,它将是未定义的。
这令人困惑,因为我认为props.navigation
是passed to all screens automatically。
如何通过TabNavigator将数据从一个屏幕传递到另一个屏幕,只使用react-navigation?我已经看到了使用Redux的答案,但我不想导入另一个库,如果我想要的是在不同反应导航器的屏幕上保持一些状态。
答案 0 :(得分:2)
似乎this.props.navigation.state.params
只能使用旧的一个参数?可能?试试这个:
doIt = () => {
this.props.navigation.setParams({results: 'one'}); // <--- set data when user clicks button.
}
console.log(this.props.navigation.state.params.results);
答案 1 :(得分:1)
我遇到了类似的问题。我有一个多页表单,客户坚持要把每个步骤都放在选项卡栏上的一个选项卡中。我使用了反应导航createMaterialTopTabNavigator
创建了导航器,却找不到在标签之间传递表单数据的简便方法。
我最终要做的是使用react的Context API,并将选项卡导航器包装在一个根表单容器中,该容器为导航器提供上下文值并在其中进行路由。这是我的操作方式:
根表单容器
// MultiScreenForm.js
imports...
import MultiScreenFormNavigator from './MultiScreenFormNavigator'
export const FormContext = React.createContext()
class MultiScreenForm extends Component {
constructor(props) {
super(props)
this.state = {
// formDataHere
formUpdaters: {
onToggleOpIn: this.handleToggleOptIn // example updater method
// other
}
}
handleToggleOptIn = () => {
// toggle opt in form data with this.setState
}
render() {
return (
<FormContext.Provider value={this.state}>
<MultiScreenFormNavigator />
</FormContext.Provider>
)
}
}
export default MultiScreenForm
示例表单页面
// ProfileForm.js
imports...
import { FormContext } from './MultiScreenForm'
class ProfileForm extends Component {
render() {
// FormContext.Consumer uses function as child pattern
return (
<FormContext.Consumer>
{ (context) => (
// our form can now use anything that we pass through the context
// earlier, we passed the root form's state including an updater
<button onPress={context.formUpdaters.onToggleOptIn} />
// ...
)
}
</FormContext.Consumer>
)
}
}
export default ProfileForm
标签导航器
// MultiScreenFormNavigator.js
imports...
import ProfileForm from './ProfileForm'
import { createMaterialTopTabNavigator } from 'react-navigation'
const MultiScreenFormNavigator = createMaterialTopTabNavigator(
{
Profile: ProfileForm,
// AnotherForm: AnotherForm
},
// { navigator options here... }
)
export default MultiScreenFormNavigator
然后,我们直接呈现MultiScreenForm而不是标签导航器。
这对我有用,但是我觉得应该有一种更简单的方法来做到这一点。我希望阅读此书的人可以分享他们的方法。
答案 2 :(得分:0)
在跨不同标签传递数据时,设置道具不起作用。我甚至尝试使用AsyncStorage,尝试在不同的标签中保存和检索它们。
我最终使用Redux来保存我的状态,到目前为止效果很好。
答案 3 :(得分:0)
@tempomax 对 AsyncStorage 进行了相同的尝试,但数据输入有所延迟。 有时,如果您的应用程序很小,则不需要Redux。
因此尝试找到一种不使用 Redux的方法。 这是我想出的
我希望回答还为时不晚。 使用 NavigationEvents 解决了该问题,并将 params 设置为Route。
选项卡的问题是您无法将参数传递给屏幕,因为如果在 createMaterialTopTabNavigator 上滑动或单击了非活动的TabBar按钮,将自动触发navigation.navigate。
这可以通过如下的NavigationEvent解决。
import React from 'react';
import { View } from 'react-native';
import { NavigationEvents } from 'react-navigation';
const MyScreen = () => (
<View>
<NavigationEvents
onWillFocus={payload => console.log('will focus',payload)}
onDidFocus={payload => console.log('did focus',payload)}
onWillBlur={payload =>
/*
if screen is about to change this will be triggred
In screen 'MyScreen2' you can get it with navigation.params
*/
this.props.navigation.navigate('MyScreen2', { name: 'Brent' })
}
onDidBlur={payload => console.log('did blur',payload)}
/>
{/*
Your view code
*/}
</View>
);
export default MyScreen;
现在您可以在MyScreen2中获取数据
/* 2. Get the param, provide a fallback value if not available */
const { navigation } = this.props;
const itemId = navigation.getParam('name', 'DefaultName');
const otherParam = navigation.getParam('otherParam', 'some default value');
答案 4 :(得分:0)
如果您将React Native Navigation版本5.x与DrawerNavigation一起使用,则可以使用
在屏幕1中:
<Button
onPress={() => {
this.props.navigation.navigate(<ScreenNameOfDrawerScreen>,
{screen:'<ScreenNameInTabDrawer>',params:{your_json_Data}});
}} />
在屏幕2中:
............
render() {
if(this.props.route.params!=undefined){
if(this.props.route.params.your_json_Data!=null){
// Use this.props.route.params.your_json_Data. It is your json data.
}
}
return (
..............