title: React Native - Pass ListView row data to new screen when button clicked?
body: <p>I'm a newbie using <strong>React Native</strong>, but using the <a href="https://nativebase.io/" rel="nofollow noreferrer">NativeBase</a> framework I've been able to put an app together for my class project. I have been able to solve most issues with the help of this community as well as the Facebook docs, but I am stuck.</p>
  
  <p>I have a ListView element that I am using to display a list of workout exercises from a JSON file, and that works well as far as I can tell. For now, data being rendered per row includes an <strong>image</strong>, <strong>title</strong>, required <strong>equipment</strong>, and exercise <strong>type</strong>. The JSON file also contains a YouTube <strong>video</strong> ID field, but I am not using it just yet because that's where I am stuck.</p>
  
  <p>What I need to do is to open a new screen when someone clicks "Watch Video", and on that screen I want to pass the value from the <strong>video</strong> field in the JSON file, from that specific row that has been clicked. This should load and play the instructional video from YouTube on the new screen, where I am using the <a href="https://github.com/inProgress-team/react-native-youtube" rel="nofollow noreferrer">React Native YouTube</a> library to achieve this.</p>
  
  <p>On the same screen, I would also like to reference the information about the exercise that I have mentioned above, so that the user knows they are looking at what they clicked.</p>
  
  <p>I have tried to engineer a solution based on what I have seen here <a href="https://stackoverflow.com/questions/37915301/select-a-row-in-listview-react-native-to-get-detail">#1</a>, here <a href="https://stackoverflow.com/questions/38662857/react-native-passing-data-from-one-screen-to-another">#2</a>, and here <a href="https://stackoverflow.com/questions/38171253/how-to-select-one-item-of-listview-in-react-native">#3</a>, but I have been unsuccessful.</p>
  
  <p>Excuse any mess in the code; I may have forgotten to revert some areas during my trial and error.</p>
  
  <p>Below is one of my <strong>Exercise Display</strong> screens:</p>
  
  <pre><code>import React, { Component } from 'react';
  import { Image, ListView } from "react-native";
  import { Container, Content, Header, Button, Icon, Item, Input, Card, 
  CardItem, Text, Thumbnail, Title, Left, Right, View, Body, Spinner, 
  ActionSheet, Toast } from 'native-base';
  import ActivityIndicator from "react-native-loading-spinner-overlay";
  import PTRView from 'react-native-pull-to-refresh';
  
  import styles from "../_overrides/styles";
  import exercises from "../../../data/exercises.json";
  
  var BUTTONS = ["30-Minute Cardio", "Bodyweight Workout", "TRX 30 
  Suspension", "Cancel"];
  var CANCEL_INDEX = 3;
  
  class CardioGuides extends Component {
  // eslint-disable-line
  constructor(props) {
      super(props);
      this.state = {
          // data listing
          isLoading: true,
          visible: false,
    showToast: false,
    clicked: '',
    searchText: ''
      };
  }
  // pull down to refresh
  _refresh() {
    return new Promise((resolve) =&gt; {
      setTimeout(()=&gt;{resolve()}, 2000)
    });
  }
  errorToast(error) {
    Toast.show({
      text: "Error loading exercise list",
      buttonText: "Okay"
    })
  }
  addSuccessToast() {
    Toast.show({
      text: "Added to " + this.state.clicked,
      buttonText: "Okay"
    })
  }
  componentDidMount() {
  return fetch("https://activ.raysfitness.co.ke/test/exercises.json")
    .then((response) =&gt; response.json())
    .then((responseJson) =&gt; {
      let ds = new ListView.DataSource({rowHasChanged: (r1, r2) =&gt; r1 !== r2});
      this.setState({
        isLoading: false,
        dataSource: ds.cloneWithRows(responseJson.resource), // reference to "resource" in the JSON file
      }, function() {
        // do something with new state
      });
    })
    .catch((error) =&gt; {
      this.setState({
        isLoading: false
      });
      this.errorToast();
    });
  }
  render() {
      // eslint-disable-line
  if (this.state.isLoading) {
    return (
              &lt;ActivityIndicator visible={this.state.isLoading} style={styles.activityIndicator}&gt;
        &lt;Spinner color="red" style={styles.activitySpinner} /&gt;
      &lt;/ActivityIndicator&gt;
    );
  }
      return (
    &lt;Container style={styles.container}&gt;
      &lt;Header searchBar style={styles.header}&gt;
        &lt;Item style={styles.searchrow}&gt;
          &lt;Button transparent style={styles.searchbtn} onPress={() =&gt; this.props.navigation.goBack()}&gt;
            &lt;Icon style={styles.searchicon} name="md-arrow-back" /&gt;
          &lt;/Button&gt;
          &lt;Input style={styles.searchinput} placeholder="Filter Exercises" value={this.state.searchText}
           onChangeText={(searchText) =&gt; this.setState({searchText})} placeholderTextColor="#CACACA" returnKeyType="search" /&gt;
          &lt;Button transparent style={styles.searchbtn}&gt;
            &lt;Icon style={styles.searchicon} name="md-search" /&gt;
          &lt;/Button&gt;
        &lt;/Item&gt;
      &lt;/Header&gt;
      &lt;PTRView onRefresh={this._refresh} &gt;
              &lt;Content padder style={{ marginTop: 0 }}&gt;
          &lt;ListView
                      dataSource={this.state.dataSource}
                      renderRow={(rowData) =&gt;
                &lt;Card style={styles.card}&gt;
                          &lt;CardItem style={{paddingLeft: 6}}&gt;
                              &lt;Left&gt;
                                  &lt;Thumbnail style={styles.cardthumb} source={{uri: `${rowData.image}`}} /&gt;
                                  &lt;Body&gt;
                                      &lt;Text style={styles.cardtitle}&gt;{`${rowData.title}`.toUpperCase()}&lt;/Text&gt;
                                      &lt;Text note style={styles.cardnote}&gt;{rowData.equipment} / {rowData.type}&lt;/Text&gt;
                                  &lt;/Body&gt;
                              &lt;/Left&gt;
                          &lt;/CardItem&gt;
                          &lt;CardItem style={{ paddingVertical: 0, paddingTop: 0, paddingLeft: 11 }}&gt;
                              &lt;Left&gt;
                                  &lt;Button iconLeft transparent style={styles.cardbtn}
                        onPress={() =&gt; this._viewExercise(rowData)}&gt;
                                      &lt;Icon active name="md-play" style={styles.cardicon} /&gt;
                                      &lt;Text style={styles.cardtext}&gt;Watch Video&lt;/Text&gt;
                                  &lt;/Button&gt;
                              &lt;/Left&gt;
                              &lt;Body&gt;
                                  &lt;Button iconLeft transparent style={styles.cardbtn}
                        onPress={() =&gt;
                          ActionSheet.show(
                            {
                              options: BUTTONS,
                              cancelButtonIndex: CANCEL_INDEX,
                              title: "Add to Workout"
                            },
                            buttonIndex =&gt; {
                              this.setState({ clicked: BUTTONS[buttonIndex] });
                              this.addSuccessToast();
                            }
                         )}
                      &gt;
                                      &lt;Icon active name="md-add" style={styles.cardicon} /&gt;
                                      &lt;Text style={styles.cardtext}&gt;Add to Workout&lt;/Text&gt;
                                  &lt;/Button&gt;
                              &lt;/Body&gt;
                              &lt;Right&gt;
                                  &lt;Button iconLeft transparent style={styles.cardbtn}&gt;
                                      &lt;Icon active name="md-bookmark" style={styles.cardicon} /&gt;
                                      &lt;Text style={styles.cardtext}&gt;Save&lt;/Text&gt;
                                  &lt;/Button&gt;
                              &lt;/Right&gt;
                          &lt;/CardItem&gt;
                      &lt;/Card&gt;
                          }
                      &gt;
                  &lt;/ListView&gt;
          &lt;View&gt;
                  &lt;Text style={styles.leadtext}&gt;{'Can\'t find what you\'re looking for? Add it!'}&lt;/Text&gt;
                  &lt;Button block style={styles.ctabtn}
                   onPress={() =&gt; this.props.navigation.navigate("AddExercise")}
                  &gt;
                      &lt;Text style={styles.ctatext}&gt;{'Add a Custom Exercise'.toUpperCase()}&lt;/Text&gt;
                  &lt;/Button&gt;
          &lt;/View&gt;
              &lt;/Content&gt;
      &lt;/PTRView&gt;
    &lt;/Container&gt;
      );
  }
  // listen for "watch view" clicks
  _viewExercise(rowData) {
      this.props.navigation.navigate("ExerciseView");
    }
  }
  export default CardioGuides;
  </code></pre>
  
  <p>And below is my <strong>Exercise View</strong> screen:</p>
  
  <pre><code>import React, { Component } from "react";
  import { Image, ListView } from "react-native";
  import { Container, Header, Title, Content, Text, H3, Button, Icon, Left, 
  Right, Body, View, Toast } from "native-base";
  import YouTube from "react-native-youtube";
  
  
  import styles from "../_overrides/styles";
  
  var title, type, equipment, video;
  const VIDEO_ID = "ZgVjj8JaGf0";
  
  class ExerciseView extends Component {
    constructor() {
      super();
      this.state = {
        showToast: false
      };
  }
  
  errorToast() {
    Toast.show({
      text: "Could not load exercise",
      buttonText: "Okay"
    })
  }
  
  render(rowData) {
  
  return (
    &lt;Container style={styles.container}&gt;
      &lt;Header style={styles.header}&gt;
        &lt;Left&gt;
          &lt;Button transparent onPress={() =&gt; this.props.navigation.goBack()}&gt;
            &lt;Icon name="md-arrow-back" /&gt;
          &lt;/Button&gt;
        &lt;/Left&gt;
        &lt;Body&gt;
          &lt;Title style={styles.title}&gt;{'View Exercise'.toUpperCase()}&lt;/Title&gt;
        &lt;/Body&gt;
        &lt;Right /&gt;
  
      &lt;/Header&gt;
  
      &lt;Content padder style={styles.content}&gt;
  
        &lt;Text style={styles.text}&gt;{"Exercise Detail\n"}&lt;/Text&gt;
        &lt;View&gt;
          &lt;YouTube
            apiKey="YOUTUBE-API-KEY-HERE"
            videoId={`${VIDEO_ID}`}   // The YouTube video ID
            play={true}             // control playback of video with true/false
            fullscreen={false}       // control whether the video should play in fullscreen or inline
            loop={true}             // control whether the video should loop when ended
            onReady={e =&gt; this.setState({ isReady: true })}
            onChangeState={e =&gt; this.setState({ status: e.state })}
            onChangeQuality={e =&gt; this.setState({ quality: e.quality })}
            onError={e =&gt; this.setState({ error: e.error })}
            style={{ alignSelf: 'stretch', height: 200 }}
          /&gt;
        &lt;/View&gt;
  
      &lt;/Content&gt;
  
    &lt;/Container&gt;
    );
    }
  }
  
  export default ExerciseView;
  </code></pre>