I want to use Modal with ListView and open That in renderRow(rowData){} Area But Does not open.
That is okey in render() Area But I Got: a red Screen Can't Find Variable: rowData
How Can I Fix That?
My Code:
import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableHighlight, ListView, Image, Modal, Linking } from 'react-native';
import photosData from '../dataset/Photos'
var Dimensions = require('Dimensions')
var { width, height } = Dimensions.get('window')
export default class MyListView extends React.Component {
constructor(props) {
super(props)
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 })
this.state = {
dataSource: ds.cloneWithRows(photosData),
modalVisible: false,
}
}
setModalVisible(visible) {
this.setState({ modalVisible: visible });
}
renderRow(rowData) {
const img = rowData.image
return (
<TouchableHighlight style={styles.containerCell}
// onPress={() => Linking.openURL(img)}
onPress={() => { this.setModalVisible(true) }}
>
<View>
<Image
// resizeMode={Image.resizeMode.contain}
// resizeMethod={"scale"}
style={{ width: width, height: 180, }}
source={{ uri: img }}
/>
<View style={styles.footerContainer}>
<View
style={styles.imageUser}
>
<Image
style={styles.imageAvatar}
// source={{ uri: rowData.user }}
source={require('../assets/icons/footer-avatar.png')}
/>
</View>
<View style={styles.footerTextContainer}>
<Text style={{ color: 'blue' }} //I can see my photos in webview
onPress={() => Linking.openURL(img)}>
Google
</Text>
<Text style={styles.text}>{rowData.food}</Text>
<Text style={[styles.text, styles.textTitle]}>{rowData.title}</Text>
<Text style={[styles.text, styles.textBy]}>By {rowData.by}</Text>
</View>
</View>
</View>
</TouchableHighlight>
)
}
render() {
const img = rowData.image
return (
<View style={styles.container}>
<Modal
animationType={"slide"}
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => { alert("Modal has been closed."), this.setModalVisible(!this.state.modalVisible) }}
>
<View style={{ marginTop: 22 }}>
<View>
<Image
// resizeMode={Image.resizeMode.contain}
// resizeMethod={"scale"}
style={{ width: width, height: 180, }}
source={{ uri: img }} // I can'ttttttttttt see my photos in Modal
/>
<TouchableHighlight onPress={() => {
this.setModalVisible(!this.state.modalVisible)
}}>
<Text>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
<ListView
style={styles.listContainer}
renderRow={this.renderRow.bind(this)}
dataSource={this.state.dataSource}
/>
</View>
);
}
}
I have pasted your code, it seem you have minor syntax error of closing bracket but I hope it is just copy-paste mistake.
First thing, you should not place your your Modal in renderRow function, it can create problem sometimes with styling and data. You can place it in main render() method.
Add function call to your rendering method if data is available and set this.setModalVisible(true).
Example:
render() {
return(
<View>
{/* other code */}
<Modal
animationType={'slide'}
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => { this.setModalVisible(false); } }
>
<View style={{ marginTop: 22 }}>
{(/*add some condition to check availability of data */)
? this.renderRow() // rendering function
: NULL}
</View>
</Modal>
</View>
);
}
EDIT after OP changed question:
Please find full code with my comment (not tested just added logic to work-around)
import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableHighlight, ListView, Image, Modal, Linking } from 'react-native';
import photosData from '../dataset/Photos'
var Dimensions = require('Dimensions')
var { width, height } = Dimensions.get('window')
export default class MyListView extends React.Component {
constructor(props) {
super(props)
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 })
this.state = {
dataSource: ds.cloneWithRows(photosData),
modalVisible: false,
currentImage: ''
}
}
setModalVisible(visible, img) {
this.setState({ modalVisible: visible, currentImage: img }); // set current image path to show it in modal
}
renderRow(rowData) {
const img = rowData.image
return (
<TouchableHighlight style={styles.containerCell}
// onPress={() => Linking.openURL(img)}
onPress={() => { this.setModalVisible(true, img) }} // pass image scr to function
>
<View>
<Image
// resizeMode={Image.resizeMode.contain}
// resizeMethod={"scale"}
style={{ width: width, height: 180, }}
source={{ uri: img }}
/>
<View style={styles.footerContainer}>
<View
style={styles.imageUser}
>
<Image
style={styles.imageAvatar}
// source={{ uri: rowData.user }}
source={require('../assets/icons/footer-avatar.png')}
/>
</View>
<View style={styles.footerTextContainer}>
<Text style={{ color: 'blue' }} //I can see my photos in webview
onPress={() => Linking.openURL(img)}>
Google
</Text>
<Text style={styles.text}>{rowData.food}</Text>
<Text style={[styles.text, styles.textTitle]}>{rowData.title}</Text>
<Text style={[styles.text, styles.textBy]}>By {rowData.by}</Text>
</View>
</View>
</View>
</TouchableHighlight>
)
}
render() {
// const img = rowData.image
return (
<View style={styles.container}>
<Modal
animationType={"slide"}
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => { alert("Modal has been closed."), this.setModalVisible(!this.state.modalVisible) }}
>
<View style={{ marginTop: 22 }}>
<View>
<Image
// resizeMode={Image.resizeMode.contain}
// resizeMethod={"scale"}
style={{ width: width, height: 180, }}
source={{ uri: this.state.currentImage }} // use currentImage scr to show on clicking list item
/>
<TouchableHighlight onPress={() => {
this.setModalVisible(!this.state.modalVisible)
}}>
<Text>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
<ListView
style={styles.listContainer}
renderRow={this.renderRow.bind(this)}
dataSource={this.state.dataSource}
/>
</View>
);
}
}
Related
UserAttemp.js
const setModal = ({ item }) => {
const perc = (item.score * 100) / item.total;
console.log("perc", perc);
if (perc >= 70) {
setImagePath(smile);
} else if (perc >= 40 && perc < 70) {
setImagePath(dis);
} else {
setImagePath(sad);
}
setTotal(item.total);
console.log("item_id",item.attempt_id);
console.log("item_total",item.total)
// setAttemp(item.attempted_question);
setScore(item.score);
setWrong(item.wrong);
setSkip(item.skip);
setModalVisible(true);
// setboolThree(false);
// setboolTwo(true);
};
const renderItem = ({ item }) => {
return (
<TouchableOpacity
style={styles.userAttemptItemContainer}
onPress={() => setModal({ item })}
>
<View>
<Text style={{alignSelf:'center',color:'black',textTransform:'uppercase'}}>{item.attempt_id}</Text>
<View
style={{ flexDirection: "row", justifyContent: "space-around" }}
>
<Text style={styles.userAttempRenderText}>Score</Text>
<Text style={styles.userAttempRenderText}>{item.score}</Text>
</View>
<Date_time
item={item}/>
</View>
</TouchableOpacity>
);
};
return (
<View>
<Loader bool={bool} />
{!bool && (
<View>
<View style={{ alignSelf: "center" }}>
<Text style={{ color: "black", fontSize: 20 }}>{title}</Text>
</View>
<FlatList
data={attempt}
renderItem={renderItem}
ListFooterComponent={<View style={{ height: 0, marginBottom: 90 }}></View>}
ListEmptyComponent={() => <EmptyListMessage />}
></FlatList>
</View>
)}
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}
>
<View style={styles.ResultModalCenterView}>
<View style={styles.ResultModalView}>
<View style={styles.ResultModalClosebuttonCon}>
<Pressable
style={[styles.ResultModalButton, styles.ResultButtonClose]}
onPress={() => setModalVisible(!modalVisible)}
>
<Icon name="close" size={20} color="black" />
</Pressable>
</View>
<ModalView
score={score}
total={total}
wrong={wrong}
title={title}
skip={skipp}
attempted={attempted}
imagePath={imagePath}
/>
</View>
</View>
</Modal>
</View>
);
};
export default UserAttemps;
Date_time.js
import React, { useState } from 'react'
import { View,Text } from 'react-native';
const Date_time=(props)=> {
const [dateBool,setDateBool]=useState(props.item?false:true);
const [timeBool,setTimeBool]=useState(props.item?false:true);
if(props.item.start_date==props.item.end_date){
setDateBool(true);
}
if(props.item.start_time==props.item.end_time){
setTimeBool(true);
}
return (
<View>
{dateBool&&<View style={{flexDirection:'row',justifyContent:'center',}}>
<Text style={{color:'black',}}>Date:</Text>
<Text style={{color:'black',marginLeft:5}}>{props.item.start_date}</Text>
</View>}
{!dateBool&&<View style={{flexDirection:'row',justifyContent:'center',}}>
<Text style={{color:'black',}}>Date:</Text>
<Text style={{color:'black',marginLeft:5}}>{props.item.start_date}</Text>
<Text style={{color:'black',marginLeft:5}}>{props.item.end_date}</Text>
</View>}
{/* <View style={{flexDirection:'row',justifyContent:'center'}}>
<Text style={{color:'black'}}>Date</Text>
<Text style={{color:'black'}}>{Date}</Text>
</View> */}
{ timeBool&& <View style={{flexDirection:'row',justifyContent:'center',}}>
<Text style={{color:'black',}}>Time:</Text>
<Text style={{color:'black',marginLeft:5}}>{props.item.start_time}</Text>
</View>}
{timeBool&&<View style={{flexDirection:'row',justifyContent:'center',}}>
<Text style={{color:'black',}}>Time:</Text>
<Text style={{color:'black',marginLeft:5}}>{props.item.start_time}</Text>
<Text style={{color:'black',marginLeft:5}}>{props.item.end_time}</Text>
</View>}
</View>
)
}
export default Date_time;
I am calling component in UserAttemp.js
I have made a component of Date_time in that I am trying to set state in the body of function component but i am getting too manay render error due to the useState hook
I want to set State in the body of function Date_time.jjs component how to set?
Updating state outside the return function, makes it go in infinite loop. It will check the condition and update the state which will cause re-render then if will again check the condition and so on... it keeps re-rendering.
Remove the if statements and handle them in initial value of useState hook. Like-
const [dateBool,setDateBool]=useState(props.item?.start_date==props.item?.end_date ? true : props.item? false :true);
const [timeBool,setTimeBool]=useState(props.item?.start_time==props.item?.end_time ? true : props.item ? false:true);
This is the start component and below the render function onPress function works fine.
import React, { useState, useEffect, useRef } from "react"
import {
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
TextInput,
KeyboardAvoidingView,
Keyboard,
Button,
} from "react-native"
import BouncyCheckbox from "react-native-bouncy-checkbox"
import { SafeAreaView } from "react-native-safe-area-context"
import { ScrollView, TouchableWithoutFeedback } from "react-native-gesture-handler"
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view"
import RNPickerSelect from "react-native-picker-select"
import Animated from "react-native-reanimated"
import BottomSheet from "reanimated-bottom-sheet"
import EventBannerSheet from "./event-banner"
export const UserInfoPhone: React.FC = () => {
const userNumberFormRef = useRef<TextInput>()
const userNumberNextFormRef = useRef<TextInput>()
const userPhoneNumberFormRef = useRef<TextInput>()
const focusToNextForm = (nextForm: any) => {
nextForm.current.focus()
}
const EssentialAgreementContainer = ({ text }) => {
return (
<View style={styles.essentialAgreementContainer}>
<View style={styles.essentialSmallBox}>
<Text style={styles.essentialAgreementText}>[필수] {text}</Text>
<TouchableOpacity style={styles.okButton}>
<Text style={styles.okButtonTitle}>보기</Text>
</TouchableOpacity>
</View>
<BouncyCheckbox
size={17}
fillColor="lightgrey"
unfillColor="lightgrey"
iconStyle={{ borderColor: "lightgrey" }}
textStyle={{ fontFamily: "JosefinSans-Regular" }}
/>
</View>
)
}
return (
<>
<SafeAreaView style={styles.container}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<KeyboardAwareScrollView>
<Image source={require("./back.png")} style={styles.backButton} />
<View style={styles.viewTitle}>
<Text style={styles.title}>휴대폰으로</Text>
<Text style={styles.title}>간편 본인인증하세요.</Text>
</View>
<View style={styles.subTitleContainer}>
<Text style={styles.subTitle}>나중에 할게요</Text>
<TouchableOpacity style={styles.okButton}>
<Text style={styles.okButtonTitle}>확인</Text>
</TouchableOpacity>
</View>
<View style={[styles.agreementContainer, styles.shadowProps]}>
<View style={styles.conditionContainer}>
<Text style={styles.agreementTitle}>본인확인 서비스에 대해 모두 동의하기</Text>
<BouncyCheckbox
size={17}
fillColor="lightgrey"
unfillColor="lightgrey"
iconStyle={{ borderColor: "lightgrey" }}
textStyle={{ fontFamily: "JosefinSans-Regular" }}
/>
</View>
<View style={styles.contour}></View>
<EssentialAgreementContainer text="서비스 이용약관 동의" />
<EssentialAgreementContainer text="통신사 이용약관 동의" />
<EssentialAgreementContainer text="개인 정보 수집 및 이용 동의" />
<EssentialAgreementContainer text="개인 제어보 제공/위탁 동의" />
<EssentialAgreementContainer text="고유식별 정보 처리" />
</View>
<View style={styles.infoForms}>
<View style={styles.nameFormContainer}>
<Text style={styles.userInfo}>성명</Text>
<TextInput
style={styles.nameForm}
onSubmitEditing={() => {
focusToNextForm(userNumberFormRef)
}}
/>
</View>
<View style={styles.personNumberFormContainer}>
<Text style={styles.userInfo}>주민등록번호 (외국인등록번호)</Text>
<View style={styles.userNumberFormContainer}>
<TextInput
style={styles.userNumberForm}
maxLength={6}
placeholder="960101"
onSubmitEditing={() => {
focusToNextForm(userNumberNextFormRef)
}}
ref={userNumberFormRef}
/>
<Text style={{ fontSize: 20 }}>-</Text>
<TextInput
style={styles.userSecondNumberForm}
maxLength={1}
ref={userNumberNextFormRef}
onSubmitEditing={() => {
focusToNextForm(userPhoneNumberFormRef)
}}
/>
</View>
</View>
<View style={styles.phoneFormContainer}>
<Text style={styles.userInfo}>휴대폰번호</Text>
<View style={styles.phoneForms}>
<View style={styles.telecome}>
<RNPickerSelect
style={{ inputAndroid: { color: "black", padding: 0, height: 20 } }}
useNativeAndroidPickerStyle={false}
onValueChange={(value) => console.log(value)}
placeholder={{ label: "통신사" }}
items={[
{ label: "SKT", value: "SKT" },
{ label: "KT", value: "KT" },
{ label: "LG U+", value: "LG U+" },
{ label: "SKT알뜰폰", value: "SKT알뜰폰" },
{ label: "KT알뜰폰", value: "KT알뜰폰" },
{ label: "LG U+알뜰폰", value: "LG U+알뜰폰" },
]}
/>
</View>
<TextInput
style={styles.phoneForm}
placeholder="010-1234-5678"
ref={userPhoneNumberFormRef}
/>
</View>
</View>
</View>
<TouchableOpacity style={styles.certificationButton}>
<Text style={styles.certificationText}>인증하기</Text>
</TouchableOpacity>
</KeyboardAwareScrollView>
</TouchableWithoutFeedback>
</SafeAreaView>
<EventBannerSheet />
</>
)
}
and this is the EventBannerSheet Component, I got this BottomSheet library and wrote it, but the onPress function doesn't work here. Also I did it before using the Checkbox library but onValueChange also didn't work in android.
import React, { useRef } from "react"
import { StyleSheet, Text, View, Image, TouchableOpacity } from "react-native"
import BottomSheet from "reanimated-bottom-sheet"
const EventBannerSheet: React.FC = () => {
const sheetRef = useRef(null)
const consoleHello = () => {
console.log("helloooooooo!!!!")
}
const renderContent = () => (
<View style={styles.bottomSheet}>
<View style={styles.sheetTextContainer}>
<Text
style={styles.sheetText}
onPress={() => {
consoleHello()
}}
>
EVENT BANNER
</Text>
<Text style={styles.sheetText}>IMG</Text>
</View>
<View style={styles.sheetCloseContainer}>
<TouchableOpacity
onPress={() => {
console.log("helloMaster123")
}}
>
<Text style={{ color: "blue" }}>오늘 하루 보지않기</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => sheetRef.current.snapTo(2)}>
<Text>닫기</Text>
</TouchableOpacity>
</View>
</View>
)
return (
<>
<BottomSheet
initialSnap={1}
ref={sheetRef}
snapPoints={[450, 350, 0]}
borderRadius={10}
renderContent={renderContent}
/>
</>
)
}
and this is stylesheet of EventBannerSheet
const styles = StyleSheet.create({
bottomSheet: {
backgroundColor: "white",
padding: 25,
height: 440,
},
sheetTextContainer: {
height: 270,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#d3d3d3",
borderRadius: 10,
},
sheetText: {
fontSize: 30,
color: "white",
},
sheetCloseContainer: {
flexDirection: "row",
justifyContent: "space-between",
marginTop: 20,
},
})
<View style={styles.bottomSheet}>
<View style={styles.sheetTextContainer}>
<TouchableOpacity
style={styles.sheetText}
onPress={() => {
consoleHello()
}}
>
<Text style={{ color: "black" }}>EVENT BANNER</Text>
</TouchableOpacity>
<Text style={styles.sheetText}>IMG</Text>
</View>
<View style={styles.sheetCloseContainer}>
<TouchableOpacity
onPress={() => {
console.log("helloMaster123")
}}>
<Text style={{ color: "blue" }}>오늘 하루 보지않기</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => sheetRef.current.snapTo(2)}>
<Text>닫기</Text>
</TouchableOpacity>
</View>
</View>
Please try the above code. I have tested the code and touchable opacity is working fine without any issue. I have added a text color for EVENT BANNER text just to test. Let me know if you need any other help.
here is the config I've made to make it work on both iOS and Android with button and horizontal drag slider
<BottomSheet
initialSnap={1}
ref={sheetRef}
snapPoints={[450, 350, 0]}
borderRadius={10}
renderContent={renderContent}
enabledContentGestureInteraction={false}
enabledInnerScrolling={false}
enabledContentTapInteraction={false}
/>
I append three attributes so i solve this problem.
And the button inside the view use TouchableOpacity from RN for iOS and TouchableOpacity from react-native-gesture-handler for Android
maybe someone can help me with that. I don't know why my onLongPress is not working. After starting my application it shows errors like in the bellow link:
https://imageupload.io/i/0eEdzuD7CI
Please help me!
import React, { useState } from "react";
import {
View,
StyleSheet,
Text,
Image,[enter image description here][1]
TouchableHighLight,
TouchableOpacity,
Dimensions,
Button,
Modal
} from "react-native";
import Icon from "react-native-vector-icons/FontAwesome"
var { width } = Dimensions.get("window");
const ListItem = (props) => {
const [modalVisible, setModalVisible] = useState(false)
return (
<View>
<Modal animationType="fade" transparent={true} visible={modalVisible} onRequestClose={() => {
setModalVisible(false)
}}>
<View>
<View>
<TouchableHighLight
underlayColor="E8E8E8"
onPress={() => {
setModalVisible(false)
}}
style={{
alignSelf: "flex-end",
position: "absolute",
top: 5,
right: 10
}}
>
<Icon name="close" size={20} />
</TouchableHighLight>
<Button title="Edit"
onPress={() => [
props.navigation.navigate("Product Form"),
setModalVisible(false)
]}
/>
<Button title="Delete"
// delete
/>
</View>
</View>
</Modal>
<TouchableOpacity
onPress={() => {
props.navigation.navigate("Product Detail", { item: props })
}}
onLongPress={() => setModalVisible(true)}
style={[styles.container, {
backgroundColor: props.index % 2 == 0 ? "white" : "gainsboro"
}]}
>
<Image
source={{
uri: props.image
? props.image
: 'https://cdn.pixabay.com/photo/2012/04/01/17/29/box-23649_960_720.png'
}}
resizeMode="contain"
style={styles.image}
/>
<Text style={styles.item}>{props.brand}</Text>
<Text style={styles.item} numberOfLines={1} ellipsizeMode="tail">{props.name}</Text>
<Text style={styles.item} numberOfLines={1} ellipsizeMode="tail">{props.category.name}</Text>
<Text style={styles.item}>$ {props.price}</Text>
</TouchableOpacity>
</View>
)
}
const styles = StyleSheet.create({
container: {
flexDirection: "row",
padding: 5,
width: width
},
image: {
borderRadius: 50,
width: width / 6,
height: 20,
margin: 2
},
item: {
flexWrap: "wrap",
margin: 3,
width: width / 6
}
})
export default ListItem;
I am new to react native I want to use for loop for showing multiple data. which is come from previous screen from API.
here is my code. I want to show full return view in for loop multiple times. I am getting data in this => undefined is not an object (evaluating 'this.props.route.params.lead_tag_number.data')
class Browse extends Component {
constructor(props) {
super(props);
this.state ={
Email:"",
}
this.handleBackButtonClick = this.handleBackButtonClick.bind(this);
}
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonClick);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButtonClick);
}
handleBackButtonClick() {
this.props.navigation.navigate("Browse");
return true;
}
state = {
categories: [],
error: [],
};
renderTab(tab) {
const { active } = this.state;
const isActive = active === tab;
return (
<TouchableOpacity
key={`tab-${tab}`}
onPress={() => this.handleTab(tab)}
style={[styles.tab, isActive ? styles.active : null]}
>
<Text size={16} medium gray={!isActive} secondary={isActive}>
{tab}
</Text>
</TouchableOpacity>
);
}
render() {
const { profile, navigation } = this.props;
const tabs = [""];
const route = this.props
for (let i = 0; i < this.props.route.params.data.length; i++) {
return (
<View style={{alignItems:"center", justifyContent:"center", }}>
<View style={styles.header}>
<Ionicons style={{paddingRight:290}} name="arrow-back" size={40}
color="black" onPress={() => navigation.navigate("Browse")} />
</View>
<Block>
<Block flex={false} row center space="between" style={styles.header}>
<Entypo style={{marginLeft:250}} onPress={() => this.props.navigation.toggleDrawer()} name="menu" size={30} color="black" />
</Block>
<Block flex={false} row style={styles.tabs}>
{tabs.map((tab) => this.renderTab(tab))}
</Block>
</Block>
<View style={{alignItems:"center", justifyContent:"center",height:140, width:"90%", marginTop:30}}>
<TouchableOpacity onPress={() => navigation.navigate("FormItems")}>
<Card center middle shadow style={{ height:80, width:"100%" }} >
<Text medium height={15} size={14}style={{ fontWeight: "bold", paddingRight:190}}>
{this.props.route.params.lead_tag_number.data[i]}
</Text>
</Card>
</TouchableOpacity>
</View>
</View>
)
}
}
}
Maybe it's problem with your for loop because you using for loop with params.data
for (let i = 0; i < this.props.route.params.data.length; i++)
and access data with params.lead_tag_number.data
this.props.route.params.lead_tag_number.data[i]
But this is not the right way to showing multiple data you can show with map function like this
render() {
const { profile, navigation } = this.props;
const tabs = [""];
const route = this.props
return (
<View style={{alignItems:"center", justifyContent:"center", }}>
<View style={styles.header}>
<Ionicons style={{paddingRight:290}} name="arrow-back" size={40}
color="black" onPress={() => navigation.navigate("Browse")} />
</View>
<Block>
<Block flex={false} row center space="between" style={styles.header}>
<Entypo style={{marginLeft:250}} onPress={() => this.props.navigation.toggleDrawer()} name="menu" size={30} color="black" />
</Block>
<Block flex={false} row style={styles.tabs}>
{tabs.map((tab) => this.renderTab(tab))}
</Block>
</Block>
{/*Use map on data as you want to show*/}
{this.props.route.params.data.map(item =>
<View style={{alignItems:"center", justifyContent:"center",height:140, width:"90%", marginTop:30}}>
<TouchableOpacity onPress={() => navigation.navigate("FormItems")}>
<Card center middle shadow style={{ height:80, width:"100%" }} >
{/*Use item*/}
<Text medium height={15} size={14}style={{ fontWeight: "bold", paddingRight:190}}>
{item}
</Text>
</Card>
</TouchableOpacity>
</View>
)}
</View>
)
}
I'm working on an app where I need to display a player with an embed youtube video. I have retrieve the data of a youtube playlist, and put them in a TouchableHighlight. I want now to display a player in a WebView, but just on top of my list. So when I'm clicking on a video, the list go down and a WebView take the place ? Is it possible ? Here is the code :
Fetching data from YTApi
_fetchPlaylist(){
if(this.state.selectedIndex === 0) {
return(
fetch(`https://www.googleapis.com/youtube/v3/playlistItems?part=snippet,contentDetails&maxResults=${results}&playlistId=PLSlVQ0kIy6qx-f5O3J3GwIEOO5Y52z43-&key=${apiKey}`)
.then(res => res.json())
.then(res => {
const videoId = []
res.items.forEach(item => {
videoId.push(item)
})
this.setState({
data:videoId
})
})
.catch(error => {
console.error(error)
})
)
}
}
displayWebView
displayVideo(videoId){
if(this.state.selectedIndex == 0){
return(
<View style = {{height:300}}>
<WebView
style={{flex:1}}
javaScriptEnabled={true}
source={{uri: `https://www.youtube.com/embed?v=x57qZ8Ym51s&list=${videoId}`}}
/>
</View>
)
} else{
return <View></View>
}
}
render
<View style = {styles.containerPlaylist}>
<ScrollView>
<View style = {styles.body}>
{
this.state.data.map((item,i) =>
<TouchableHighlight
key = {item.id.videoId}
onPress = {()=> this.displayVideo(item.id.videoID)}>
<View style = {styles.vids}>
<Image
source = {{uri: item.snippet.thumbnails.medium.url}}
style = {{width: 120, height: 90,marginVertical:30, flexDirection:'column', alignSelf:'flex-start', backgroundColor:'#fff', resizeMode:'contain'}}
/>
<Text style = {styles.vidText}>{item.snippet.title}</Text>
</View>
</TouchableHighlight>
)}
</View>
</ScrollView>
</View>
Thanks
You need to keep webview in your layout and then need to manage two state,
to show and hide webview/video
to change the url of webview/video
Initialize the state like this along with your other state:
this.state = {
showVideo: false,
videoUrl: "default youtube url or empty string"
}
then create your layout like this and adjust your styling as per your need:
<View style={styles.containerPlaylist}>
<ScrollView>
{this.state.showVideo &&
<View style={{ height: 300 }}>
<WebView
style={{ flex: 1 }}
javaScriptEnabled={true}
source={{ uri: this.state.videoUrl }}
/>
</View>
}
<View style={styles.body}>
{
this.state.data.map((item, i) =>
<TouchableHighlight
key={item.id.videoId}
onPress={() => this.displayVideo(item.id.videoID)}>
<View style={styles.vids}>
<Image
source={{ uri: item.snippet.thumbnails.medium.url }}
style={{ width: 120, height: 90, marginVertical: 30, flexDirection: 'column', alignSelf: 'flex-start', backgroundColor: '#fff', resizeMode: 'contain' }}
/>
<Text style={styles.vidText}>{item.snippet.title}</Text>
</View>
</TouchableHighlight>
)}
</View>
</ScrollView>
</View>
and change your function something like this to display video which has been clicked:
displayVideo(videoId) {
this.setState({
videoUrl: `https://www.youtube.com/embed?v=x57qZ8Ym51s&list=${videoId}`
showVideo: true
});
}