注意
这个答案是为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.js 和 Screen2.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.js 的App.js。 MainNavigation.js 设置了一个带有两个屏幕的StackNavigator,Screen1.js 和Screen2.js。 Screen1 已设置为我们的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>
)
}
}
现在我们可以在Screen1 和Screen2 之间导航
将值从Screen1 发送到Screen2
要在Screen1 和Screen2 之间发送一个值,涉及两个步骤。首先我们必须发送它,其次我们必须捕获它。
我们可以通过将值作为第二个参数传递来发送它。注意文本值是如何包含在对象中的。
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 的最简单方法是从Screen1 向Screen2 传递一个函数,该函数将使用您想要的值更新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;
在生命周期事件中捕获值(Screen1 到 Screen2)
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'}
/>
小吃