React Navigation - 如何在TabNavigator中的不同屏幕上传递数据?

时间:2018-05-18 13:45:58

标签: react-native react-navigation

我有一个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.navigationpassed to all screens automatically

如何通过TabNavigator将数据从一个屏幕传递到另一个屏幕,只使用react-navigation?我已经看到了使用Redux的答案,但我不想导入另一个库,如果我想要的是在不同反应导航器的屏幕上保持一些状态。

5 个答案:

答案 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 (
    ..............