React-native - Passing data from one screen to another
<p>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 <code>listview</code> and where pressing a row opens a screen displaying user's data. </p>

<p>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.</p>

<p>I set up an navigator in <code>index.android.js</code></p>

<pre><code>import React from 'react';
import {
  AppRegistry,
  Navigator,
} from 'react-native';

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

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

        return undefined;
      }}
    /&gt;
  );
}

AppRegistry.registerComponent('reactest', () =&gt; MyIndex);
</code></pre>

<p>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 <code>listview</code> : </p>

<pre><code>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&amp;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) =&gt; r1 !== r2 });
    this.state = {
      jsonData: datasource.cloneWithRows([]),
      ds: datasource,
    };
  }
  _handlePress() {
    return fetch(url)
      // convert to json
      .then((response) =&gt; response.json())
      // do some string manipulation on json
      .then(({ results }) =&gt; {
        const newResults = results.map((user) =&gt; {
          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) =&gt; {
        this.setState({
          jsonData: this.state.ds.cloneWithRows(results),
        });
      });
  }
  renderRow(rowData: string) {
    return (
      &lt;TouchableHighlight
        onPress={() =&gt; {
          this.props.navigator.push({
            component: ContactDetails,
          });
        }}
      &gt;
        &lt;View style={styles.listview_row}&gt;
          &lt;Image
            source={{ uri: rowData.picture.thumbnail }}
            style={{ height: 48, width: 48 }}
          /&gt;
          &lt;Text&gt;
            {rowData.name.title} {rowData.name.first} {rowData.name.last}
          &lt;/Text&gt;
        &lt;/View&gt;
      &lt;/TouchableHighlight&gt;
    );
  }
  render() {
    const view = (
      &lt;View style={styles.container}&gt;
        &lt;TouchableOpacity
          onPress={() =&gt; this._handlePress()}
          style={styles.button}
        &gt;
          &lt;Text&gt;Fetch results?&lt;/Text&gt;
        &lt;/TouchableOpacity&gt;
        &lt;ListView
          enableEmptySections
          dataSource={this.state.jsonData}
          renderRow={(rowData) =&gt; this.renderRow(rowData)}
          onPress={() =&gt; this._handleRowClick()}
        /&gt;
      &lt;/View&gt;
    );

    return view;
  }
}
</code></pre>

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

<pre><code>import React, {
} from 'react';

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

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

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

<p>At this point I got this error : </p>

<blockquote>
  <p>undefined is not an object (evaluating 'this.props.title')</p>
</blockquote>

<p>I have tried many things such as : </p>

<pre><code>this.props.navigator.push({
    component: ContactDetails,
    title: rowData.name.title,
    first: rowData.name.first,
    last: rowData.name.last,
});
</code></pre>

<p>or </p>

<pre><code>this.props.navigator.push({
    component: ContactDetails,
    props: {
        title: rowData.name.title,
        first: rowData.name.first,
        last: rowData.name.last,
    }
});
</code></pre>

<p>or</p>

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

<p>But to no avail.</p>

<p>I also read that I should use redux. Am I doing something wrong ?</p>

<p><strong>EDIT:</strong> The problem is here : </p>

<pre><code>&lt;TouchableHighlight
    onPress={() =&gt; {
      this.props.navigator.push({
        component: ContactDetails,
      });
    }}
&gt;
</code></pre>

<p>I assume I should pass some parameters there, but whatever I tried above failed.</p>