React-native-将数据从一个屏幕传递到另一个屏幕 [英] React-native - Passing data from one screen to another

查看:76
本文介绍了React-native-将数据从一个屏幕传递到另一个屏幕的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习如何使用react-native,因此我建立了一个小型应用程序,该应用程序从服务器获取用户列表,并在listview中显示它,然后在其中按一行的位置打开一个屏幕,显示用户的数据.

I am trying to learn how to use react-native, so I am putting up a small app that fetch a list of users from a server, displays it in a listview and where pressing a row opens a screen displaying user's data.

我将导航器设置为从一个屏幕转到另一个屏幕.在该行上按下时,我可以打开一个新屏幕,但是我不知道如何将数据传递到这个新屏幕.

I set up a navigator to go from one screen to another. When pressing on the row I am able to open a new screen but I can't figure how to pass data to this new screen.

我在index.android.js

import React from 'react';
import {
  AppRegistry,
  Navigator,
} from 'react-native';

import ContactList from './src/containers/ContactList.js';

function MyIndex() {
  return (
    <Navigator
      initialRoute={{ name: 'index', component: ContactList }}
      renderScene={(route, navigator) => {
        if (route.component) {
          return React.createElement(route.component, { navigator });
        }

        return undefined;
      }}
    />
  );
}

AppRegistry.registerComponent('reactest', () => MyIndex);

首先,我显示一个带有按钮和一个空列表视图的屏幕(ContactList.js),按下按钮后,我获取了一些用于更新listview的JSON数据:

First I display a screen with a button and an empty listview (ContactList.js), after pressing the button, I fetch some JSON data that are used to update the listview :

import React, { Component, PropTypes } from 'react';
import {
  Text,
  View,
  TouchableOpacity,
  TouchableHighlight,
  ListView,
  Image,
} from 'react-native';

import styles from '../../styles';
import ContactDetails from './ContactDetails';

const url = 'http://api.randomuser.me/?results=15&seed=azer';

export default class ContactList extends Component {
  static propTypes = {
    navigator: PropTypes.object.isRequired,
  }
  constructor(props) {
    super(props);

    const datasource = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
    this.state = {
      jsonData: datasource.cloneWithRows([]),
      ds: datasource,
    };
  }
  _handlePress() {
    return fetch(url)
      // convert to json
      .then((response) => response.json())
      // do some string manipulation on json
      .then(({ results }) => {
        const newResults = results.map((user) => {
          const newUser = {
            ...user,
            name: {
              title: `${user.name.title.charAt(0).toUpperCase()}${user.name.title.slice(1)}`,
              first: `${user.name.first.charAt(0).toUpperCase()}${user.name.first.slice(1)}`,
              last: `${user.name.last.charAt(0).toUpperCase()}${user.name.last.slice(1)}`,
            },
          };

          return newUser;
        });

        return newResults;
      })
      // set state
      .then((results) => {
        this.setState({
          jsonData: this.state.ds.cloneWithRows(results),
        });
      });
  }
  renderRow(rowData: string) {
    return (
      <TouchableHighlight
        onPress={() => {
          this.props.navigator.push({
            component: ContactDetails,
          });
        }}
      >
        <View style={styles.listview_row}>
          <Image
            source={{ uri: rowData.picture.thumbnail }}
            style={{ height: 48, width: 48 }}
          />
          <Text>
            {rowData.name.title} {rowData.name.first} {rowData.name.last}
          </Text>
        </View>
      </TouchableHighlight>
    );
  }
  render() {
    const view = (
      <View style={styles.container}>
        <TouchableOpacity
          onPress={() => this._handlePress()}
          style={styles.button}
        >
          <Text>Fetch results?</Text>
        </TouchableOpacity>
        <ListView
          enableEmptySections
          dataSource={this.state.jsonData}
          renderRow={(rowData) => this.renderRow(rowData)}
          onPress={() => this._handleRowClick()}
        />
      </View>
    );

    return view;
  }
}

当按下一行时,它会打开一个新屏幕ContactDetails.js,该屏幕应该显示用户数据:

When a row is pressed, it opens a new screen ContactDetails.js, which is supposed to display user's data :

import React, {
} from 'react';

import {
  Text,
  View,
} from 'react-native';

import styles from '../../styles';

export default function ContactDetails() {
  return (
    <View style={styles.container}>
      <Text>{this.props.title}</Text>
      <Text>{this.props.first}</Text>
      <Text>{this.props.last}</Text>
    </View>
  );
}

这时我遇到了这个错误:

At this point I got this error :

未定义不是对象(正在评估"this.props.title")

undefined is not an object (evaluating 'this.props.title')

我尝试了很多事情,例如:

I have tried many things such as :

this.props.navigator.push({
    component: ContactDetails,
    title: rowData.name.title,
    first: rowData.name.first,
    last: rowData.name.last,
});

this.props.navigator.push({
    component: ContactDetails,
    props: {
        title: rowData.name.title,
        first: rowData.name.first,
        last: rowData.name.last,
    }
});

this.props.navigator.push({
    component: ContactDetails,
    passProps: {
        title: rowData.name.title,
        first: rowData.name.first,
        last: rowData.name.last,
    }
});

但无济于事.

我还读到我应该使用redux.我做错什么了吗?

I also read that I should use redux. Am I doing something wrong ?

问题在这里:

<TouchableHighlight
    onPress={() => {
      this.props.navigator.push({
        component: ContactDetails,
      });
    }}
>

我假设我应该在那儿传递一些参数,但是上面我尝试的所有操作都失败了.

I assume I should pass some parameters there, but whatever I tried above failed.

推荐答案

所以问题似乎出在这里:

So the problem seems to lie here:

<Navigator
  initialRoute={{ name: 'index', component: ContactList }}
  renderScene={(route, navigator) => {
    if (route.component) {
      return React.createElement(route.component, { navigator });
    }

    return undefined;
  }}
/>

在renderScene函数中,您确实收到了路由(并使用route.component),但没有传递route.props或route.passProps或任何您想调用的东西!从那时我在Navigator的源代码中看到的,您应该在创建它时拥有完整的路由对象.因此,您应该能够传递道具.

In the renderScene function, you do receive the route (and use route.component) but you don't pass your route.props or route.passProps or what ever you want to call it! And from what I see in the source of Navigator at that moment you should have the full route object as you created it. So you should be able to pass your props along.

例如:

<Navigator
  initialRoute={{ name: 'index', component: ContactList }}
  renderScene={(route, navigator) => {
    if (route.component) {
      return React.createElement(route.component, { navigator, ...route.props });
    }

    return undefined;
  }}
/>

// push
<TouchableHighlight
  onPress={() => {
    this.props.navigator.push({
      component: ContactDetails,
      props: { /* ... */ }
    });
  }}
>

您还可以设置redux,但这不是必需的.虽然如果您的应用程序越来越大,您应该真正考虑使用外部存储!

You could also setup redux, but that's not a requirement. Though if your app gets bigger you should really consider using an external store!

更新:

还有另一个问题.

您使用功能组件.功能组件没有this.他们在参数中接收道具.

You use a functional components. Functional components don't have a this. They receive the props in parameter.

所以应该像这样:

export default function ContactDetails(props) {
  return (
    <View style={styles.container}>
      <Text>{props.title}</Text>
      <Text>{props.first}</Text>
      <Text>{props.last}</Text>
    </View>
  );
}

这篇关于React-native-将数据从一个屏幕传递到另一个屏幕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆