在React Native Navigator中如何在组件之间传递值

20

如何在React Native中使用Navigator从场景A传递数据到场景B?

我正在使用以下代码进入场景B:

this.props.navigator.push({
    id: "MainPage",
    name: 'mainPage'
});
6个回答

27

你需要在导航器上设置passProps属性。最近有一些关于这个问题的例子,具体可以参考这里这里

<Navigator
  initialRoute={{name: 'Main', component: Main, index: 0}}
  renderScene={(route, navigator) =>    {
    return React.createElement(<YourComponent />, { ...this.props, ...route.passProps, navigator, route } );
  }} />
或者
<Navigator
  initialRoute={{name: 'Main', component: Main, index: 0}}
  renderScene={(route, navigator) => {
      <route.component {...route.passProps} navigator={navigator} route={route} />
     }
   }
 />

如果你只是想了解功能最基础的设置,我已经在这里设置了一个项目(链接),你可以参考一下,并且我也把代码复制粘贴在下面。

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Navigator,
  Image,
  TouchableHighlight, TouchableOpacity
} = React;

class Two extends React.Component {
    render(){
    return(
        <View style={{marginTop:100}}>
          <Text style={{fontSize:20}}>Hello From second component</Text>
          <Text>id: {this.props.id}</Text>
          <Text>name: {this.props.name}</Text>
            <Text>name: {this.props.myVar}</Text>
        </View>
    )
  } 
}

class Main extends React.Component {
  gotoNext(myVar) {
   this.props.navigator.push({
      component: Two,
      passProps: {
        id: 'page_user_infos',
        name: 'page_user_infos',
        myVar: myVar,
      }
    })
  }

  render() {
    return(
      <View style={{flex: 4, flexDirection: 'column', marginTop:100}}>
        <TouchableHighlight style={{ height:40, borderWidth:1, marginBottom:10, backgroundColor: '#ddd'}} name='Pole' onPress={ () => this.gotoNext('This is a property that is being passed') }>
          <Text style={{textAlign:'center'}}>Go to next page</Text>
        </TouchableHighlight>
      </View> 
    )
  }
}

class App extends React.Component {
  render() {

    return (
      <Navigator
                style={{flex:1}}
          initialRoute={{name: 'Main', component: Main, index: 0}}
          renderScene={(route, navigator) =>    {
            if (route.component) {
                          return React.createElement(route.component, { ...this.props, ...route.passProps, navigator, route } );
                      }
                }}
          navigationBar={
            <Navigator.NavigationBar routeMapper={NavigationBarRouteMapper} />
      } />
);
}
}


var NavigationBarRouteMapper = {
  LeftButton(route, navigator, index, navState) {
    if(index > 0) {
      return (
      <TouchableHighlight  style={{marginTop: 10}} onPress={() => {
            if (index > 0) {
              navigator.pop();
            } 
        }}>
       <Text>Back</Text>
     </TouchableHighlight>
 )} else {
 return null}
 },
  RightButton(route, navigator, index, navState) {
    return null;
  },
  Title(route, navigator, index, navState) {
    return null
  }
};


var styles = StyleSheet.create({

});

AppRegistry.registerComponent('App', () => App);

如果你的组件分别存在不同的文件中,请确保在发送组件中导入接收组件。例如:import MyComponentWhichReceivesPassProps from './MyComponentWhichReceivesPassProps' - Orlando
@Nader 谢谢!!!这正是我在寻找的。React的导航文档根本没有什么帮助。 - pnkflydgr

4

我建议你参照这个示例,设置导航器。在index场景中放置导航器并导入所有必要的组件。接着,定义一个renderScene()函数来处理所有基于名称(或ID,就像你做的那样)的路由。不要将组件对象直接传递给导航器的push方法,因为如果你这样做,你将需要在具体视图中导入该组件。我以前用这种方式,遇到了很多问题,所以我只是提醒你,如果你遇到任何问题,请考虑这种方法。

  renderScene(route, navigator) {

    if(route.name == 'root') {
      return <Root navigator={navigator} />
    }
    if(route.name == 'register') {
      return <Register navigator={navigator} />
    }
    if(route.name == 'login') {
      return <Login navigator={navigator} />
    }
    if(route.name == 'home') {
      return <Home navigator={navigator} {...route.passProps} />
    }
    if(route.name == 'update') {
      return <Update navigator={navigator} {...route.passProps} />
    }

  }


1
使用 switch 代替 if。 - Jagadish Upadhyay

0
如果您正在使用 react-native-navigation,只需根据 documentation 的说明,在您的 params 对象中添加 passProps 即可。

eg.:

this.props.navigator.push({
  screen: 'example.Screen',
  title: 'Screen Title',
  passProps: {
    id: 'MainPage',
    name: 'mainPage'
  }
})

0
有时候 pass 属性不起作用(至少对我来说是这样),所以我会将它直接传递到路由对象中。
nav.push({
        id: 'MainPage',
        name: 'LALA',
        token: tok
      });

所以要在下一个场景中访问它,我使用

var token = this.props.navigator.navigationContext.currentRoute.token;

虽然这种“访问”有点复杂,但它是百分之百的可靠。传递属性可能有效,也可能无效。此外,您还可以通过路由对象本身传递属性,从而避免以其他方式发送它所带来的麻烦。

这可能不是正确的方法,但我觉得它更加方便一些。


0

1. 在从场景A传递数据到场景B时,您必须在导航器标签中指定您也要通过路由传递数据。 例如:

if(route.name == 'home') {
      return <Home navigator={navigator} data={route.data} />
    }

从场景A发送数据 例如:this.props.navigator.push({name:'sceneB',data:{name:this.state.name},});

在场景B中像这样访问数据 例如:this.props.data.name 然后你就可以从场景A获取数据到场景B了


0

您还可以通过以下方式将参数从SceneA传递到SceneB。假设_handlePressOnClick()是在SceneA屏幕上某个按钮单击事件中编写的。

_handlePressOnClick(){ //this can be anything
 this.props.navigator.push({
    name: "sceneB", //this is the name which you have defined in _renderScene
    otherData: {
      dataA: "data1"
    }
 })
}

然后在您实现导航器的_renderScene中定义数据,就像这样

_renderScene(route, navigator) {        
    switch(route.name) {
        case "sceneA":
            return (
                <sceneA navigator={navigator} />
            );
        break;
        case "sceneB":
            return (
                <sceneB navigator={navigator} otherData={route.otherData}/>
            );
        break;
  }

别忘了像这样导入你的视图文件

import sceneA from './sceneA';
import sceneB from './sceneB';

现在在sceneB文件中,您可以按照以下方式访问您的otherData

var {dataA} = this.props.otherData;

or

constructor(props){
  super(props);
  this.state={
     otherData: this.props.otherData
  }
}

那么在您的render()方法中,您可以使用state访问otherData。

<Text>{this.state.otherData.dataA}</Text>

你也可以使用Redux来维护全局状态,它可以通过操作和属性自动访问。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接