2017-07-27 110 views
0

我是一個新手使用反應原生,但使用NativeBase框架我已經能夠爲我的課程項目放在一起的應用程序。在這個社區以及Facebook文檔的幫助下,我已經能夠解決大多數問題,但我陷入困境。React Native - 點擊按鈕時將ListView行數據傳遞到新屏幕?

我有一個ListView元素,我正在使用它來顯示JSON文件中的鍛鍊練習列表,而且據我所知,這個練習效果很好。目前,每行渲染的數據包括圖片,標題,要求設備和練習類型。 JSON文件還包含一個YouTube 視頻 ID字段,但我尚未使用它,因爲這是我卡住的地方。

我需要做的是打開一個新的屏幕,當有人點擊「觀看視頻」,並在該屏幕上,我想從JSON文件中的視頻視頻字段中的值傳遞該特定行被點擊。這應該在新屏幕上加載和播放來自YouTube的教學視頻,我使用React Native YouTube庫實現此目的。

在同一屏幕上,我還想引用上面提到的有關練習的信息,以便用戶知道他們正在查看他們點擊的內容。

我試圖根據我在這裏看到的#1,在這裏#2,這裏#3工程師解決方案,但我一直沒有成功。

原諒代碼中的任何混亂;在我的試驗和錯誤期間,我可能忘記恢復某些區域。

下面是我鍛鍊顯示屏幕之一:

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) => { 
    setTimeout(()=>{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) => response.json()) 
    .then((responseJson) => { 
    let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => 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) => { 
    this.setState({ 
     isLoading: false 
    }); 
    this.errorToast(); 
    }); 
} 
render() { 
    // eslint-disable-line 
if (this.state.isLoading) { 
    return (
      <ActivityIndicator visible={this.state.isLoading} style={styles.activityIndicator}> 
     <Spinner color="red" style={styles.activitySpinner} /> 
    </ActivityIndicator> 
); 
} 
    return (
    <Container style={styles.container}> 
    <Header searchBar style={styles.header}> 
     <Item style={styles.searchrow}> 
     <Button transparent style={styles.searchbtn} onPress={() => this.props.navigation.goBack()}> 
      <Icon style={styles.searchicon} name="md-arrow-back" /> 
     </Button> 
     <Input style={styles.searchinput} placeholder="Filter Exercises" value={this.state.searchText} 
     onChangeText={(searchText) => this.setState({searchText})} placeholderTextColor="#CACACA" returnKeyType="search" /> 
     <Button transparent style={styles.searchbtn}> 
      <Icon style={styles.searchicon} name="md-search" /> 
     </Button> 
     </Item> 
    </Header> 
    <PTRView onRefresh={this._refresh} > 
      <Content padder style={{ marginTop: 0 }}> 
     <ListView 
        dataSource={this.state.dataSource} 
        renderRow={(rowData) => 
       <Card style={styles.card}> 
         <CardItem style={{paddingLeft: 6}}> 
          <Left> 
           <Thumbnail style={styles.cardthumb} source={{uri: `${rowData.image}`}} /> 
           <Body> 
            <Text style={styles.cardtitle}>{`${rowData.title}`.toUpperCase()}</Text> 
            <Text note style={styles.cardnote}>{rowData.equipment}/{rowData.type}</Text> 
           </Body> 
          </Left> 
         </CardItem> 
         <CardItem style={{ paddingVertical: 0, paddingTop: 0, paddingLeft: 11 }}> 
          <Left> 
           <Button iconLeft transparent style={styles.cardbtn} 
         onPress={() => this._viewExercise(rowData)}> 
            <Icon active name="md-play" style={styles.cardicon} /> 
            <Text style={styles.cardtext}>Watch Video</Text> 
           </Button> 
          </Left> 
          <Body> 
           <Button iconLeft transparent style={styles.cardbtn} 
         onPress={() => 
         ActionSheet.show(
          { 
          options: BUTTONS, 
          cancelButtonIndex: CANCEL_INDEX, 
          title: "Add to Workout" 
          }, 
          buttonIndex => { 
          this.setState({ clicked: BUTTONS[buttonIndex] }); 
          this.addSuccessToast(); 
          } 
         )} 
        > 
            <Icon active name="md-add" style={styles.cardicon} /> 
            <Text style={styles.cardtext}>Add to Workout</Text> 
           </Button> 
          </Body> 
          <Right> 
           <Button iconLeft transparent style={styles.cardbtn}> 
            <Icon active name="md-bookmark" style={styles.cardicon} /> 
            <Text style={styles.cardtext}>Save</Text> 
           </Button> 
          </Right> 
         </CardItem> 
        </Card> 
         } 
        > 
       </ListView> 
     <View> 
       <Text style={styles.leadtext}>{'Can\'t find what you\'re looking for? Add it!'}</Text> 
       <Button block style={styles.ctabtn} 
       onPress={() => this.props.navigation.navigate("AddExercise")} 
       > 
        <Text style={styles.ctatext}>{'Add a Custom Exercise'.toUpperCase()}</Text> 
       </Button> 
     </View> 
      </Content> 
    </PTRView> 
    </Container> 
    ); 
} 
// listen for "watch view" clicks 
_viewExercise(rowData) { 
    this.props.navigation.navigate("ExerciseView"); 
    } 
} 
export default CardioGuides; 

而下面是我運動查看屏幕:

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 (
    <Container style={styles.container}> 
    <Header style={styles.header}> 
     <Left> 
     <Button transparent onPress={() => this.props.navigation.goBack()}> 
      <Icon name="md-arrow-back" /> 
     </Button> 
     </Left> 
     <Body> 
     <Title style={styles.title}>{'View Exercise'.toUpperCase()}</Title> 
     </Body> 
     <Right /> 

    </Header> 

    <Content padder style={styles.content}> 

     <Text style={styles.text}>{"Exercise Detail\n"}</Text> 
     <View> 
     <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 => this.setState({ isReady: true })} 
      onChangeState={e => this.setState({ status: e.state })} 
      onChangeQuality={e => this.setState({ quality: e.quality })} 
      onError={e => this.setState({ error: e.error })} 
      style={{ alignSelf: 'stretch', height: 200 }} 
     /> 
     </View> 

    </Content> 

    </Container> 
); 
    } 
} 

export default ExerciseView; 
+0

1.你應該[寫有清晰的問題陳述你的問題(https://stackoverflow.com/help/how-to-ask )。我花了一些通讀來明確你的問題是什麼。 2.你在使用反應導航嗎?如果是這樣,當你調用'this.props.navigation.navigate(「ExerciseView」)時,你爲什麼不只是[傳遞params](https://reactnavigation.org/docs/intro/#Passing-params) '然後用'this.props.navigation.state'在新屏幕上訪問它們? –

+0

@MichaelCheng感謝您的回覆。我編輯了這個問題;我不確定現在是否更清楚?我現在也在閱讀文檔,看看如何按照建議通過參數。希望我會有一些運氣。 –

+0

已解決!感謝一羣@MichaelCheng。我覺得有點笨,但非常感謝! :D –

回答

0

(發佈代表OP)的

我已經能夠用一個小方向解決這個問題。對於別人誰可能有類似的問題,這是我做的:

由於我使用的反應導航,我通過我需要在onPress函數中使用的導航數據,就像這樣:

onPress={() => this.props.navigation.navigate("ExerciseView", { title: 
`${rowData.title}`, video: `${rowData.video}` })} 

然後訪問的新屏幕上的值,就像這樣:

render() { 
const { params } = this.props.navigation.state; 
    return (
    .... 
    <Text style={styles.text}>{`${params.title} \n`}</Text> 
    <View> 
     <YouTube 
     .... 
     videoId={`${params.video}`} // The YouTube video ID 
     .... 
     /> 
    </View> 
    .... 
    ); 
}