【问题标题】:Pass Data between Pages in React native在 React Native 中的页面之间传递数据
【发布时间】:2018-10-10 10:08:45
【问题描述】:

我刚接触原生反应,我一直在追随。

我正在使用下面的代码执行导航(单击警报视图按钮时)。

const {navigation} = this.props.navigation;
…
.
.
 { text: 'Done', onPress:() => {
              navigate.push(HomeScreen);}

如何在 React Native 中将数据传递到另一个页面?我可以声明参数全局并分配给它吗?

执行此操作的正确方法是什么?我该怎么做?

【问题讨论】:

  • 你在用react-navigation吗?

标签: react-native navigation


【解决方案1】:

注意

这个答案是为react-navigation: "3.3.0" 写的。由于有更新的版本可用,这可能会带来变化,您应该确保检查实际的documentation

react-navigation 中的页面之间传递数据相当简单。文档here

中有明确说明

为了完整起见,让我们创建一个小应用程序,允许我们从一个屏幕导航到另一个屏幕之间传递值。在这个例子中,我们将只传递字符串,但也可以传递数字、对象和数组。

App.js

import React, {Component} from 'react';
import AppContainer from './MainNavigation';
export default class App extends React.Component {
  render() {
    return (
      <AppContainer />
    )
  }
}

MainNavigation.js

import Screen1 from './Screen1';
import Screen2 from './Screen2';
import { createStackNavigator, createAppContainer } from 'react-navigation';

const screens = {
  Screen1: {
    screen: Screen1
  },
  Screen2: {
    screen: Screen2
  }
}

const config = {
  headerMode: 'none',
  initialRouteName: 'Screen1'
}

const MainNavigator = createStackNavigator(screens,config);
export default createAppContainer(MainNavigator);

Screen1.jsScreen2.js

import React, {Component} from 'react';
import { View, StyleSheet, Text, Button } from 'react-native';

export default class Screen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white'
  }
});

这里有 4 个文件。我们将导入MainNavigation.jsApp.jsMainNavigation.js 设置了一个带有两个屏幕的StackNavigatorScreen1.jsScreen2.jsScreen1 已设置为我们的StackNavigator 的初始屏幕。

在屏幕之间导航

我们可以通过使用从Screen1导航到Screen2

this.props.navigation.navigate('Screen2');

我们可以通过使用从Screen2回到Screen1

this.props.navigation.goBack();

所以Screen1中的代码变成了

export default class Screen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Button title={'Go to screen 2'} onPress={() => this.props.navigation.navigate('Screen2')} />
      </View>
    )
  }
}

Screen2 中的代码变为:

export default class Screen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Button title={'Go back'} onPress={() => this.props.navigation.goBack()} />
      </View>
    )
  }
}

现在我们可以在Screen1Screen2 之间导航

将值从Screen1 发送到Screen2

要在Screen1Screen2 之间发送一个值,涉及两个步骤。首先我们必须发送它,其次我们必须捕获它。

我们可以通过将值作为第二个参数传递来发送它。注意文本值是如何包含在对象中的。

this.props.navigation.navigate('Screen2', {text: 'Hello from Screen 1' });

我们可以通过以下操作在Screen2 中捕获它,getParams 中的第一个值是key,第二个值是默认值。

const text = this.props.navigation.getParams('text','nothing sent');

所以Screen1 现在变成了

export default class Screen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Button 
         title={'Go to screen 2'} 
         onPress={() => this.props.navigation.navigate('Screen2',  { 
           text: 'Hello from screen 1' 
         })} />
      </View>
    )
  }
}

Screen2 中的代码变为:

export default class Screen extends React.Component {
  render() {
    const text =  this.props.navigation.getParam('text', 'nothing sent')
    return (
      <View style={styles.container}>
        <Text>{text}</Text>
        <Button 
         title={'Go back'} 
         onPress={() => this.props.navigation.goBack()} />
      </View>
    )
  }
}

将值从Screen2 发送回Screen1

我发现将值从Screen2 发送到Screen1 的最简单方法是从Screen1Screen2 传递一个函数,该函数将使用您想要的值更新Screen1 中的状态发送

所以我们可以更新Screen1 使其看起来像这样。首先我们在 state 中设置一个初始值。然后我们创建一个更新状态的函数。然后我们将该函数作为参数传递。我们将在Text 组件中显示来自Screen2 的捕获值。

export default class Screen1 extends React.Component {

  state = {
    value: ''
  }

  receivedValue = (value) => {
    this.setState({value})
  }

  render() {
    return (
      <View style={styles.container}>
        <Button 
          title={'Go to screen 2'} 
          onPress={() => this.props.navigation.navigate('Screen2', {
            text: 'Hello from Screen 1', 
            receivedValue: this.receivedValue } 
            )} />
          <Text>{this.state.value}</Text>
      </View>
    )
  }
}

请注意,我们传递函数 receivedValue 的方式与之前传递 text 的方式相同。

现在我们必须捕获Screen2 中的值,并且我们以与之前非常相似的方式来执行此操作。我们使用getParam 来获取值,记住设置我们的默认值。然后当我们按下 Go back 按钮时,我们更新它以首先调用receivedValue 函数,并传入我们想要发回的文本。

export default class Screen2 extends React.Component {

  render () {
    const text =  this.props.navigation.getParam('text', 'nothing sent');
    const receivedValue = this.props.navigation.getParam('receivedValue', () => {});
    return (
      <View style={styles.container}>
        <Button 
          title={'Go back'} 
          onPress={() => {
            receivedValue('Hello from screen 2')
            this.props.navigation.goBack()
          }} />
          <Text>{text}</Text>
      </View>
    );
  }
}

使用getParam 的替代方案

可以不使用getParam 方法,而是直接访问这些值。如果我们这样做,我们将无法设置默认值。然而它是可以做到的。

Screen2 中,我们可以执行以下操作:

const text = this.props.navigation.state.params.text;
const receivedValue = this.props.navigation.state.params.receivedValue;

在生命周期事件中捕获值(Screen1Screen2

react-navigation 允许您使用生命周期事件捕获值。我们有几种方法可以做到这一点。我们可以使用NavigationEvents,也可以使用componentDidMount中设置的监听器

这里是如何使用NavigationEvents进行设置

import React, {Component} from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { NavigationEvents } from 'react-navigation'; // you must import this


export default class Screen2 extends React.Component {

    state = {
      text: 'nothing passed'
    }

  willFocusAction = (payload) => {
    let params = payload.state.params;
    if (params && params.value) {
      this.setState({value: params.value});
    }
  }


  render() {
    return (
      <View style={styles.container}>
        <NavigationEvents
        onWillFocus={this.willFocusAction}

        />
        <Text>Screen 2</Text>
        <Text>{this.state.text}</Text>
      </View>
    )
  }
}

这是使用componentDidMount中的侦听器的方法

export default class Screen2 extends React.Component {

  componentDidMount () {
    // we add the listener here
    this.willFocusSubscription = this.props.navigation.addListener('willFocus', this.willFocusAction);
  }

  componentWillUmount () {
    // we remove the listener here
    this.willFocusSubscription.remove()
  }

  state = {
    text: 'nothing passed'
  }

  willFocusAction = (payload) => {
    let params = payload.state.params;
    if (params && params.value) {
      this.setState({value: params.value});
    }
  }

  render() {
    return (
      <View style={styles.container}>
        <Text>Screen 2</Text>
        <Text>{this.state.text}</Text>
      </View>
    )
  }
}

通过组件传递导航

在上面的示例中,我们在屏幕之间传递值。有时我们在屏幕上有一个组件,我们可能想从中导航。只要该组件在作为导航器一部分的屏幕中使用,我们就可以做到。

如果我们从初始模板开始构建两个按钮。一个是功能组件,另一个是 React 组件。

MyButton.js

// this is a functional component
import React, {Component} from 'react';
import { View, StyleSheet, Text, TouchableOpacity } from 'react-native';

export const MyButton = ({navigation, value, title}) => {
  return (
    <TouchableOpacity onPress={() => navigation.navigate('Screen2', { value })}>
      <View style={styles.buttonStyle}>
        <Text>{title}</Text>
      </View>
    </TouchableOpacity>
  )
}

const styles = StyleSheet.create({
  buttonStyle: {
    width: 200,
    height: 60,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'red'
  }
});

MyOtherButton.js

// this is a React component
import React, {Component} from 'react';
import { View, StyleSheet, Text, TouchableOpacity } from 'react-native';

export default class MyOtherButton extends React.Component {

  render() {
    const { navigation, value, title } = this.props; 
    return (
    <TouchableOpacity onPress={() => navigation.navigate('Screen2', { value })}>
      <View style={styles.buttonStyle}>
        <Text>{title}</Text>
      </View>
    </TouchableOpacity>
    )
  }
}

const styles = StyleSheet.create({
  buttonStyle: {
    width: 200,
    height: 60,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'yellow'
  }
});

无论组件的类型如何,请注意导航是一个道具。我们必须将导航传递给组件,否则它将无法工作。

Screen1.js

import React, {Component} from 'react';
import { View, StyleSheet, Text, Button } from 'react-native';
import { MyButton } from './MyButton';        
import MyOtherButton from './MyOtherButton';  

export default class Screen1 extends React.Component {

  render() {
    return (
      <View style={styles.container}>
        <Text>Screen 1</Text>
        <MyButton 
          title={'Press my button'} 
          navigation={this.props.navigation}
          value={'this is a string passed using MyButton'}
        />
        <MyOtherButton 
          title={'Press my other button'} 
          navigation={this.props.navigation}
          value={'this is a string passed using MyOtherButton'}
        />
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white'
  }
});

注意Screen1.js,因为它包含在 StackNavigator 中,它可以访问this.props.navigation。我们可以将它作为道具传递给我们的组件。只要我们在组件中使用它,我们就应该能够使用组件自己的功能进行导航。

<MyButton 
  title={'Press my button'} 
  navigation={this.props.navigation} // pass the navigation here
  value={'this is a string passed using MyButton'} 
/>

小吃

【讨论】:

  • 有没有办法在不触发导航的情况下将值从 screen1 传递到 screen2?
  • 有很多不同的方法,这真的取决于你的应用程序设置。最简单的可能是使用事件发射器或 AsyncStorage,更多涉及的是使用 redux 设置。我建议将您的情况写成一个新问题,以便您可以清楚地表达您需要做的所有事情,因为 SO 上的 cmets 并不允许进行详细的讨论。一方面,这里的代码格式不好;其次,你被限制在 600 个字符以内,所以很难充分表达自己。
  • 感谢您的详细回答,我现在对导航 getParam 有了更多了解)))
  • 如何从平面列表中传递对象?
【解决方案2】:

1) 在主屏幕上:-

初始化:-

constructor(props) {
    super(props);
    this.navigate = this.props.navigation.navigate; }

发送:-

this.navigate("DetailScreen", {
            name: "Detail Screen",
            about:"This is Details Screen Page"
          });

2) 在详细屏幕上:-

初始化:-

constructor(props) {
    super(props);
    this.params = this.props.navigation.state.params;
}

检索数据:-

console.log(this.params.name);
console.log(this.params.about);

【讨论】:

  • 如果您在任何元素中显示,您也会显示为 {this.params.name}
  • 谢谢,很简单。
【解决方案3】:
const {navigate} = this.props.navigation;

…
.
.
 { text: 'Done', onPress:() => {
              navigate('homeScreen',...params);}

你可以得到像这样的参数

const {params} = this.props.navigation.state

【讨论】:

    【解决方案4】:

    HomeScreen.js

    this.props.navigation.navigate('Screen2',{ user_name: 'aaa',room_id:'100' });
    

    Screen2.js

    const params = this.props.route.params;
    user_name = params.user_name;
    room_id = params.room_id
    

    【讨论】:

    • 如何从平面列表中传递对象?
    【解决方案5】:

    您可以使用react-navigation 轻松发送和接收您的参数,如下所示

    发送参数

    {
       text: 'Done',
       onPress: () => {
           this.props.navigation.navigate(
               HomeScreen,
               {param1: 'value1', param2: 'value2'}
           );
       }
    }
    

    获取参数HomeScreen:

    const { navigation } = this.props;
    var param1 = navigation.getParam('param1', 'NO-VALUE');
    var param2 = navigation.getParam('param2', 'NO-VALUE');
    

    'NO-VALUE' 是默认值,如果没有所需的参数

    【讨论】:

      【解决方案6】:

      我假设您正在使用 react-navigation。因此,在 react-navigation 中,我们可以分两部分传递数据:

      1. 通过将参数放在对象中作为 navigation.navigate 函数的第二个参数,将参数传递给路由:

        this.props.navigation.navigate('RouteName', { /* params go here */ })

      2. 读取屏幕组件中的参数:

        this.props.navigation.getParam(paramName, someDefaultValue)

        警报按钮

            <Button
              title="Alert View"
              onPress={() => {
                this.props.navigation.navigate('alerts', {
                  itemId: 86,
                  otherParam: 'anything you want here',
                });
              }}
            />
        

      屏幕:

      const itemId = navigation.getParam('itemId', 'NO-ID');
      const otherParam = navigation.getParam('otherParam', 'some default value')
      

      【讨论】:

        【解决方案7】:

        屏幕 1:

        <Button title="Go Next"
        onPress={() => navigation.navigate('SecondPage', { paramKey: userName })} />
        

        屏幕 2:

        const SecondPage = ({route}) => {
            ....
            ....
            <Text style={styles.textStyle}>
                Values passed from First page: {route.params.paramKey}
            </Text>
            ....
            ....
        }
        

        【讨论】:

          猜你喜欢
          • 2019-02-13
          • 2018-01-10
          • 1970-01-01
          • 1970-01-01
          • 2019-02-21
          • 2018-07-08
          • 1970-01-01
          • 2015-06-19
          相关资源
          最近更新 更多