在React Native中的页面之间传递数据 [英] Pass Data between Pages in React native
问题描述
我是新来的本地人,所以我被困在下面.
我正在使用以下代码执行导航(单击警报视图按钮时).
const {navigation} = this.props.navigation;
…
.
.
{ text: 'Done', onPress:() => {
navigate.push(HomeScreen);}
如何在React native中将数据传递到另一个页面?我可以将参数声明为全局参数并直接分配给它吗?
执行此操作的正确方法是什么,我将如何处理?
注意
此答案是为
react-navigation: "3.3.0"
编写的.由于存在可用的较新版本,可能会带来变化,因此,请确保检查实际的文档. /p>
在react-navigation
中的页面之间传递数据非常简单. 此处
为完整起见,我们创建一个小应用程序,使我们能够从一个屏幕导航到另一个屏幕之间传递值.在此示例中,我们将仅传递字符串,但可以传递数字,对象和数组.
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
用两个屏幕Screen1.js
和Screen2.js
设置StackNavigator
. Screen1
已设置为我们的StackNavigator
的初始屏幕.
在屏幕之间导航
我们可以通过使用
从Screen1
导航到Screen2
this.props.navigation.navigate('Screen2');
,我们可以使用
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>
)
}
}
从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
以使其看起来像这样.首先,我们在状态中设置一个初始值.然后,我们创建一个将更新状态的函数.然后,我们将该函数作为参数传递.我们将在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>
)
}
}
请注意,我们以与之前传递text
相同的方式传递函数receivedValue
.
现在,我们必须在Screen2
中捕获值,并且以与以前非常相似的方式进行操作.我们使用getParam
来获取值,记住要设置默认值.然后,当我们按下返回按钮时,我们对其进行更新以首先调用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'}
/>
小吃
- 这是小吃用于传递参数.
- 这是小吃用于传递参数并捕获生命周期事件.
- 这是小吃将导航传递给组件
Im new to react native and I'm stuck at following.
Im performing navigation (when clicked on alert view button) using the code below.
const {navigation} = this.props.navigation;
…
.
.
{ text: 'Done', onPress:() => {
navigate.push(HomeScreen);}
How can I pass data to another Page in React native? Can I declare the parameter global and just assign to it?
What would be the correct way of performing this and how would I go about it?
Note
This answer was written for
react-navigation: "3.3.0"
. As there are newer versions available, which could bring changes, you should make sure that you check with the actual documentation.
Passing data between pages in react-navigation
is fairly straight forward. It is clearly explained in the documentation here
For completeness let's create a small app that allows us to navigate from one screen to another passing values between the screens. We will just be passing strings in this example but it would be possible to pass numbers, objects and arrays.
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
and 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'
}
});
Here we have 4 files. The App.js
which we will import the MainNavigation.js
. The MainNavigation.js
sets up a StackNavigator
with two screens, Screen1.js
and Screen2.js
. Screen1
has been set as the initial screen for our StackNavigator
.
Navigating between screens
We can navigate from Screen1
to Screen2
by using
this.props.navigation.navigate('Screen2');
and we can go back to Screen1
from Screen2
by using
this.props.navigation.goBack();
So code in Screen1
becomes
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>
)
}
}
And code in Screen2
becomes:
export default class Screen extends React.Component {
render() {
return (
<View style={styles.container}>
<Button title={'Go back'} onPress={() => this.props.navigation.goBack()} />
</View>
)
}
}
Now we can navigate between Screen1
and Screen2
Sending values from Screen1
to Screen2
To send a value between Screen1
and Screen2
, two steps are involved. First we have to send it, secondly we have to capture it.
We can send a value by passing it as a second parameter. Notice how the text value is contained in an object.
this.props.navigation.navigate('Screen2', {text: 'Hello from Screen 1' });
And we can capture it in Screen2
by doing the following, the first value in getParams
is the key
the second value is the default value.
const text = this.props.navigation.getParams('text','nothing sent');
So Screen1
now becomes
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>
)
}
}
And code in Screen2
becomes:
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>
)
}
}
Sending values from Screen2
back to Screen1
The easiest way I have discovered to send a value from Screen2
to Screen1
is to pass a function to Screen2
from Screen1
that will update the state in Screen1
with the value that you want to send
So we can update Screen1
to look like this. First we set an initial value in state. Then we create a function that will update the state. Then we pass that function as a parameter. We will display the captured value from Screen2
in a Text
component.
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>
)
}
}
Notice that we are passing the function receivedValue
in the same way that we passed the text
earlier.
Now we have to capture the value in Screen2
and we do that in a very similar way that we did previously. We use getParam
to get the value, remembering to set our default. Then when we press our Go back button we update it to call the receivedValue
function first, passing in the text that we want to send back.
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>
);
}
}
Alternatives to using getParam
It is possible to not use the getParam
method and instead access the values directly. If we were to do that we would not have the option of setting a default value. However it can be done.
In Screen2
we could have done the following:
const text = this.props.navigation.state.params.text;
const receivedValue = this.props.navigation.state.params.receivedValue;
Capturing values in lifecycle events (Screen1
to Screen2
)
react-navigation
allows you to capture values using the lifecycle events. There are a couple of ways that we can do this. We could use NavigationEvents
or we could use listeners set in the componentDidMount
Here is how to set it up using 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>
)
}
}
Here is how to do it using listeners in the 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>
)
}
}
Passing navigation via components
In the above examples we have passed values from screen to screen. Sometimes we have a component on the screen and we may want to navigate from that. As long as the component is used within a screen that is part of a navigator then we can do it.
If we start from our initial template and construct two buttons. One will be a functional component the other a React component.
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'
}
});
Regardless of the type of component, notice that navigation is a prop. We must pass navigation to the component otherwise it will not work.
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'
}
});
Notice in Screen1.js
as it is contained in a StackNavigator it will have access to this.props.navigation
. We can pass that through to our component as a prop. As long as we use that in our component then we should be able to navigate by using the components own functionality.
<MyButton
title={'Press my button'}
navigation={this.props.navigation} // pass the navigation here
value={'this is a string passed using MyButton'}
/>
Snacks
- Here is a snack for passing params.
- Here is a snack for passing params and capturing in lifecycle events.
- Here is a snack passing navigation to components
这篇关于在React Native中的页面之间传递数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!