1. 목적
: 이번엔 Firebase와 연동해둔 FlatList에서 얻은 동영상 정보를
iframe을 통해 재생할 수 있도록 연동한다.
2. 실험시작
시도 1 : <TouchableOpacity>를 이용해서 onPress props를 통해 실행시킬것이다.
처음엔 간단하게 onPress를 이용해 videoId가 제대로 들어오는지 확인해보자.
다음과 같이 onPress작동시, 실행 될 함수를 선언해주고,
TouchableOpacity에 onPress넣고 실행.
결과 : const로 선언한 함수에서 item이란 인자를 못찾는다.
ScrollView에서는 map함수로 재깍재깍 찾았으나, 얘는 map함수로 돌아가는 것이 아니라 못찾나 추측중.
const onPress = ({ item }) => {
return console.log(item.id.videoId)
}
....
return (
<View>
<Iframe />
<FlatList
data={state}
renderItem={({ item }) => (
<View style={styles.cardContainer}>
<TouchableOpacity style={styles.card} onPress={onPress}>
는 아니었다.
공식문서처럼 onPress에 대한 선언을 간단하게 한게 화근이었다.
아래와 같이 하니 잘 받는다. (머쓱)
return문에 있는 함수에서 onPress에 대한 props인 item을 내보내 줘야 읽을 수 있었다.
props의 기본정의를 참고했다.
const onPress = ({ item }) => {
return console.log(item.id.videoId)
}
...
return (
<View>
<Iframe />
<FlatList
data={state}
renderItem={({ item }) => (
<View style={styles.cardContainer}>
<TouchableOpacity style={styles.card} onPress={() => onPress({ item })}>
시도 3 :
이제는 onPress를 이용해 iframe에 videoId를 전달해줄 차례
구글링을 참조한 결과 navigation옵션을 사용해 인자를 전달할 수 있다고 한다.
일단 해본 결과 당연히 대실패
먼저 flatlist.js파일의 onPress에 navigation.navigate를 걸고, 이동할 경로인 'iframe'과 전달한 {item}을 넣어봤다.
그리고, iframe.js에서 videoId= { } 괄호안에 video.id.videoId가 바로 안들어가므로,
const CardID를 이용해 치환용으로 선언해준 후 CardID를 대입했다.
실패의 원인은 기본지식 부족인듯 하므로, 공식문서를 보고 계속 시도해볼 수 밖에 ㅎㅎ
FlatList.js
return (
<View>
<Iframe />
<FlatList
data={state}
renderItem={({ item }) => (
<View style={styles.cardContainer}>
<TouchableOpacity style={styles.card} onPress={() => navigation.navigate('frame', { item })}>
iframe.js
const CardID = <FirebaseFL>{ item.id.videoId }</FirebaseFL>
return (
<View>
<YoutubePlayer
height={200}
play={playing}
videoId={
// "pUoOzaU9rw4"
CardID
}
onChangeState={onStateChange}
/>
<Button title={playing ? "pause" : "play"} onPress={togglePlaying} />
</View>
);
시도 4 :
iframe의 videoId라는 인자 안에 firebase로부터 가져온 videoID를 대입해주기 위해,
아예 flatlist.js 안에 iframe 코드를 합쳐서 심어주었다. 여기까진 무리없이 작동.
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { ActivityIndicator, FlatList, View, Text, Image, StyleSheet, TouchableOpacity, Button, Alert } from 'react-native';
import { firebase_db } from '../firebaseConfig';
import YoutubePlayer from "react-native-youtube-iframe";
export default function Users() {
//-------Flatlist 적용을 위한 useState 등 선언부분-----
const [loading, setLoading] = useState(true); // Set loading to true on component mount
const [state, setState] = useState([])
// -----iframe 적용부분----------------------------------
const [playing, setPlaying] = useState(false);
const onStateChange = useCallback((state) => {
if (state === "ended") {
setPlaying(false);
Alert.alert("video has finished playing!");
}
}, []);
const togglePlaying = useCallback(() => {
setPlaying((prev) => !prev);
}, []);
// ---------- console.log로 video 확인할 수 있는 함수부분
const onPress = ({ item }) => {
return (
setCardID(item)
// console.log(item.id.videoId)
)
}
// ---Firebase를 대입하기 위한 부분 --------
useEffect(() => {
firebase_db.ref('/items').once('value').then((snapshot) => {
console.log("파이어베이스에서 데이터 가져왔습니다!!")
let items = snapshot.val();
setState(items)
setLoading(false);
});
}, []);
//ActivityIndicator는 로딩 중 돌아가는 동그라미
if (loading) {
return <ActivityIndicator />;
}
// return부분 -----
return (
<View>
{/* iframe을 보여주기 위한 부분 */}
<View>
<YoutubePlayer
height={200}
play={playing}
videoId={비디오 아이디를 대입}
onChangeState={onStateChange}
/>
<Button title={playing ? "pause" : "play"} onPress={togglePlaying} />
</View>
{/* Flatlist 부분 */}
<FlatList data={state} renderItem={({ item }) => (
<View style={styles.cardContainer}>
<TouchableOpacity style={styles.card} onPress={() => onPress({ item })}>
<Image style={styles.cardImage} source={{ uri: item.snippet.thumbnails.medium.url }} />
<View style={styles.cardText}>
<Text style={styles.cardTitle} numberOfLines={1}>{item.snippet.title}</Text>
<Text style={styles.cardDesc} numberOfLines={3}>{item.snippet.description}</Text>
<Text style={styles.cardDate}>{item.snippet.publishedAt}</Text>
<Text>Video ID: {item.id.videoId}</Text>
</View>
</TouchableOpacity>
</View>
)} />
</View >
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
cardContainer: {
// marginTop: 10,
backgroundColor: '#fff',
},
card: {
flex: 1,
//컨텐츠들을 가로로 나열
//세로로 나열은 column <- 디폴트 값임
flexDirection: "row",
margin: 10,
borderBottomWidth: 0.5,
borderBottomColor: "#eee",
paddingBottom: 10
},
cardImage: {
flex: 1,
width: 100,
height: 100,
borderRadius: 10,
},
cardText: {
flex: 2,
flexDirection: "column",
marginLeft: 10,
},
cardTitle: {
fontSize: 20,
fontWeight: "700"
},
cardDesc: {
fontSize: 15
},
cardDate: {
fontSize: 10,
color: "#A6A6A6",
}
});
여기서 onPress에 의해 videoID가 바뀔때마다 iframe에 적용해주어야 하므로,
새로운 useState를 선언해주었다. 초기 띄워줄 동영상의 videoId는 useState([ 여기 ])안에 넣어주자.
* 여기서 새롭게 알게된 부분 : 필자는 디지몬 butterfly를 좋아해서 넣었으나,
'동영상 소유자가 다른 웹사이트에서 재생할 수 없도록 설정했습니다.'라는 안내가 뜬다.
즉, 업로드한 소유자가 타 사이트 공개를하지 않으면 못쓴다느 소리다..ㄷㄷ 갓 to the 저작권
export default function Users() {
//-------Flatlist 적용을 위한 useState 등 선언부분-----
const [loading, setLoading] = useState(true); // Set loading to true on component mount
const [state, setState] = useState([])
const [cardID, setCardID] = useState(["pUoOzaU9rw4"])
그 다음, useState를 선언해주었으니 이번엔 함수를 선언해줄 차례다.
함수는 전에 만든 onPress를 수정해서 썼다.
당연히 끌어와 사용할 인자로 data를 받아 치환되는 {item}을 받아오고,
return문을 통해 setter변수를 videoId에 맞는 json 경로를 지정해준다.
console.log는 필요없으니 지워줬다.
const onPress = ({ item }) => {
return (
setCardID(item.id.videoId)
)
}
마지막으로 메인 return문에 삽입해둔 iframe 태그인 <YoutubePlayer>안의 인자인 videoId={ 여기 }에
getter변수인 cardID를 입력해주면. 끝@!
return (
<View>
{/* iframe을 보여주기 위한 부분 */}
<View>
<YoutubePlayer
height={200}
play={playing}
videoId={cardID}
onChangeState={onStateChange}
/>
<Button title={playing ? "pause" : "play"} onPress={togglePlaying} />
</View>
정상작동 완료! (성공!)
'React-native > 실패일지' 카테고리의 다른 글
[실패일지] iframe에서 연속재생 반복재생 구현하기 (0) | 2022.05.27 |
---|---|
[실패일지] realtime database에 여러 파일 올려 관리하기 (0) | 2022.05.27 |
[실패일지] Search bar 연동 중 쿼리문제 (0) | 2022.05.24 |
[실패일지] ScrollView를 Infinite Flatlist로 대체하기 (0) | 2022.05.21 |
[실패일지] 부모컴포넌트에서 자식 컴포넌트로 props 전달하기 (0) | 2022.05.20 |