我是一個新手使用反應原生,但使用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;
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'在新屏幕上訪問它們? –
@MichaelCheng感謝您的回覆。我編輯了這個問題;我不確定現在是否更清楚?我現在也在閱讀文檔,看看如何按照建議通過參數。希望我會有一些運氣。 –
已解決!感謝一羣@MichaelCheng。我覺得有點笨,但非常感謝! :D –