json - React Native - 单击按钮时将 ListView 行数据传递到新屏幕?

标签 json listview react-native youtube react-native-listview

我是使用 的新手 react 原生 ,但使用 NativeBase框架我已经能够为我的类项目组合一个应用程序。在这个社区以及 Facebook 文档的帮助下,我已经能够解决大多数问题,但我被困住了。

我有一个 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;

下面是我的练习 View 屏幕:
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;

最佳答案

(代表 OP 发布)。

我已经能够通过一点方向来解决这个问题。对于可能有类似问题的其他人,我就是这样做的:

由于我使用的是 react-navigation,因此我在 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>
     ....
    );
 }

关于json - React Native - 单击按钮时将 ListView 行数据传递到新屏幕?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45356521/

相关文章:

android - 如何用编辑文本填充 ListView ?

c# - WPF 的有效拖放启用 ListView 实现?

java - 如何动态更改 JavaFX 中 ListView 中项目的背景

reactjs - 如何使用 createAsyncThunk 帮助程序分派(dispatch) AsyncThunk

c# - 模型绑定(bind)和继承 ASP MVC 5

javascript - 将 JSON 分配为属性

java - 在 Avro Schema 中定义空字符串

json - 使用 Axios 从 Laravel Controller 捕获错误

javascript - 世博会 react native 元素类型无效 : expected a string or a class/function but got: undefined

android - 当Android Webrtc应用程序在后台,来电时,如何将来电屏幕调到前台?