@@ 너무 장황해져서 사용법을 찜하기, 페이지만들기, 찜해제 3단계로 나누어 정리함.
각 폐이지 링크는 아래와 같으며 1편부터 보는것이 이해가 쉬움
1편_찜하기(create) : https://radpro.tistory.com/71
2편_찜페이지(read and update) : https://radpro.tistory.com/73
3편_찜해제(delete) : https://radpro.tistory.com/72
-----------------------------------------------------------------------------------------------------------------------------
1. 목적
: 노래듣기 어플에 사용될 플레이리스트를 구현할 생각이다.
방식은 Likepage를 구현하는 형식으로, 하트버튼으로 선택한 항목을 Likepage에 해당 키값을 저장하고,
저장된 키값으로 구성된 리스트를 Playlist로 보이게 구현하고자 한다.
구현하고자 하는 기능은
ㄱ. 좋아요 버튼 (Heart) => clear
ㄴ. 플레이리스트(Likepage)
1) firebase내 realtime database에 CRUD로 작성방식
: 쓰기는 push()함수 사용, 지우기는 revome( ) 사용
2) 프로젝트 안에 자체 Like.JSON 파일에 작성방식
:
ㄷ. 연속재생
ㄹ. 랜덤재생
ㅁ. 반복재생
ㅂ. 오디오만 재생
ㅅ. 화면 꺼짐 상태에서도 재생
2. 방법
ㄱ. 좋아요 버튼 만들기
1) 버튼을 구성할 아이콘을 import 해준다.
react-native에 Pressable을 넣어준다.
import { AntDesign } from '@expo/vector-icons';
import { ..., Pressable } from 'react-native';
2) 좋아요 버튼에 반응할 useState를 선언해준다.
const [favorite, setFavorite] = useState();
3) Like에 반응할 함수를 선언해준다.
: return문에서 작성할 onPress에 반응할 함수이며, 추후 Likepage로 옮기는 기능을 설정할 것이다.
const Like = () => {
setFavorite(!favorite);
}
4) return문에 UI를 작성한다.
필자는 Like라는 이름의 함수로 선언해 주었으며,
삼항연산자를 통해 true값은 Like, false값은 undo Like로 설정해뒀다.
default값은 undo Like다.
return (
...
<View style={styles.heartBotton}>
{favorite ?
<Pressable onPress={() => Like()}>
<AntDesign name="heart" size={30} color="#eb4b4b" />
</Pressable>
:
<Pressable onPress={() => Like()}>
<AntDesign name="hearto" size={30} color="#999" />
</Pressable>
}
</View>
...
)
5) Style값을 조정해 아이콘을 중앙에 놓아준다.
const styles = StyleSheet.create({
...
heartBotton: {
alignItems: "center",
justifyContent: "center"
}
...
});
6) 좋아요 버튼을 이용해 DB에 찜하기(데이터 넣기) (=insert = set)
우선 expo-constants를 설치 후 import 해준다.
yarn add expo-constants
import Constants from 'expo-constants';
constants를 이용한다는 것은, 임의의 아이디를 만들어 지정해준다는 뜻이다.
( 참고문서 : https://ran-318.tistory.com/71?category=978007 )
다음으로 firebase의 공식 코드를 이용한다.
함수이름은 본인이 편한대로 짓는다.(찜하기 버튼 onPress에 넣을 함수이름)
.ref앞에 내가 firebaseConfig를 export한 이름 적는다. (필자는 firebase_db라고 export했다)
.ref의 관호 안은 realtime database에 저장할 새로운 json값은 괄호 안에 있는 것처럼 경로를 작성할 것이란 뜻이다.
풀어서 설명하자면, /like/user_id/state.idx의 경로라는 것인데,
like라는 새로운 최상위 키값을 만들어 주고, 그 안에 constants.installationId로 자동으로 받은 아이디로 키값이 생기고,
그 안에는 우리가 firebase를 치환받은 getter변수인 state에 인덱스 값인 idx를 붙여 참조한다는 뜻이다.
그렇게 얻은 state 정보를 저장(set)한다는 것이다.
그 아래 setFavorite(!favorite)은 하트 색상변경용 변수다
function Like() {
const user_id = Constants.installationId;
firebase_db.ref('/like/' + user_id + '/' + state.idx).set(state)
setFavorite(!favorite);
}
7) 좋아요 취소(찜 해제) (=delete=remove)
이름은 UnLike로 했다.
가장 까다로운 부분중 하나다. realtime database는 user_id 아래로 임의의 키값을 지정하고,
그 안에 데이터를 push한다. 이는 타임스탬프 등의 기능을 하는 임의의 코드를 만들기 위함이다.
문제는 해당 키값에 대응하여 선언할 변수를 제공하지 않는다. 미칠노릇이다.
왜냐하면 경로로 설정할 변수를 제공하지 않는다는 말이기 때문이다.
따라서 직접 변수를 만들어야한다.
여기서 내가 사용하는 방식은 아래와 같다.
a) 우선 FlatList에서 선택한 카드가 무엇인지 구분하기 위해 index라는 props를 새로 선언해준다.
b) 선언한 index를 UnLike라는 함수에서 사용하기 위해 내보내기 해준다.
c) firebase에서 on() 메소드로 데이터를 받아오는 하위 항목에서
Object.keys()를 이용해 키값만 리스트로 모두 받아온다.
(즉, item로 받아오던 Obeject.values()와 반대의 기능이라 보시면 된다)
d) 새로 useState를 선언해주고, 받아온 키값리스트를 setter변수에 할당해준다.
e) useState로 받아오는 getter변수를 UnLike함수 안에서 사용할 것이다.
getter변수[ index ] 형태를 통해, FlatList를 통해 받아온 인덱스 값에 해당하는 키값만 추출해 낸다.
f) 추출한 변수를 이용해 firebase.ref( 경로 )로 경로를 지정해준다.
g) 상단의 경로 뒤에 .remove()를 붙여주면 완성
FlatList 부분
<FlatList
data={state}
...
keyExtractor={(item, index) => index.toString()}
renderItem={({ item, index }) => (
// {item, index} 부분처럼 , index 넣으시면 됩니다.
<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.cardDate}>{index}</Text>
// 인덱스 넘버를 확인하기 위해 넣어논 Text태그. 없어도 무방합니다.
</View>
<View style={styles.LikeButton}>
<View style={styles.heartBotton}>
// 반응에 따른 하트 렌더링 구현은 수정할 예정
{favorite ?
<Pressable onPress={() => Like({ item })} >
<AntDesign name="hearto" size={30} color="#999" />
</Pressable>
:
<Pressable onPress={() => UnLike({ index })} >
// UnLike( 여기 ) 부분에 {index}로 인덱스 내보내기 한 상태
<AntDesign name="heart" size={30} color="#eb4b4b" />
</Pressable>
}
</View>
//------------------------------------------------------------------------------------------
firebase에서 키값 리스트 받아오는 방법
const [fireKey, setFireKey] = useState();
//우선 useState를 선언해준다. 필자는 firekey라고 했다.
useEffect(() => {
setTimeout(() => {
firebase
.ref(`/본인이_지정한_임의의 키값_직전까지의_경로`)
.on('value', (snapshot) => {
const Like_List = (snapshot.val());
if (Like_List === null) {
Alert.alert('<찜 없음>', '목록이 없습니다!')
} else {
setFireKey(Object.keys(Like_List))
// 구하고자 하는 키값리스트를 받는 코드. Like_List는 임의의 키값에서 시작하는 json데이터다.(키값이 포함됨)
setState(Object.values(Like_List))
// 이 코드는 위와 반다로 키값을 제외한 밸류값 전체를 받아오는 코드. state라는 getter변수를 이용해 FlatList에 item로 할당되어있다.
//------------------------------------------------------------------------------------------
UnLike 함수 선언부분
function UnLike({ index }) {
// FlatList의 UnLike 선언에서 index를 받아오는 형태이다. {index} 있어야 사용이 가능하니 잊지말자.
console.log(fireKey[index])
//realtime database에서 받아온 키값 리스트 중에서 원하는 카드의 인덱스값에 해당하는 키값만 추출하는게 잘 나오는지 확인하기 위한 터미널 출력코드
// 없어도 무방하다.
let FBKey = fireKey[index]
// 추출한 하나의 키값을 변수 선언한다. firebase 내 경로에 넣기 위함이다.
firebase.ref(`/본인이_지정한_임의의 키값_직전까지의_경로/${FBKey}`).remove()
.then(() => { Alert.alert('<찜 해제 완료>'); })
//상단의 firebase에서 받아온 경로에, 방금 추출한 경로에 대한 변수를 이용해 최종 경로를 지정해주는 부분.
// .remove()는 괄호안에 따로 뭐가 들어갈 수 없고, .ref()뒤에만 올 수 있다.
// 삭제 메소드이다.
setFavorite(false);
//하트의 렌더링을 설정해주기 위한 useState
}
ㄴ. 플레이 리스트 구현
1) 찜버튼
: 상단의 좋아요 버튼이 한번에 상태변화가 일어나는 문제가 있어 분리시켰다.
찜 버튼을 누르면 Likepage에 추가되는 구조를 만들것이다
자세한 설명은 링크 참고 : https://radpro.tistory.com/69
realtime database 찜하기 구현
1. 사용조건 ㄱ. realtime database에 저장된 json 데이터가 있다. ㄴ. FlatList가 구현되어 있다. ㄷ. 아이콘 확장 import import { AntDesign } from '@expo/vector-icons'; 2. 사용방법 1) FlatList 안..
radpro.tistory.com
2) Likepage.js
: Like라는 키값안에 들어간 데이터를 읽기위해선, 리얼타임 데이터베이스에서 임의로 지정하는 하위 키값의 경로를
제거해서 읽어야 한다. (경로를 지정할 마땅한 변수가 없기 때문)
이때, on( )과 once( )가 있다.
- once( ) 사용시 : 데이터를 한 번만 읽어낸다.
- on ( ) 사용시 : 데이터가 바뀔때마다 읽어낸다.
- ( )안에 넣는 것 : value, child_added, child_change 등이 있다. (이 덕분에 child개념을 학습할 수 있었다.)
- 임의의 키값을 지정할 수 없으므로 Object.values(치환변수)를 이용해 아예 스킵해버린다.
즉, 해당 키값 안의 value값만 읽어온다는 뜻이다. 키값 지정을 할 필요가 없어진다.
* 이때, 경로상에 user_ID를 넣으면, 하나의 user_ID에 임의의 키값들이 push되어 append되는 구조가 되므로,
user_ID가 변화되지 않아서 혹은 push단계에서 임의로 생성해준 user_Id를 인지못해서,
on( )을 써도 refresh가 되지 않는다. (이거 찾는다고 일주일 내리 날림...98시간...)
따라서, push단계에서 user_Id는 자제하자... 아니면 아예 push마다 user_id를 새로 부여해주는 방식을 채택하자.
이게 문제였다.
const user_id = Constants.installationId;
이건 user_id 적용시 코드
function Like({ item, index }) {
const user_id = Constants.installationId;
firebase_db.ref(`/like/${user_id}`).push(item)
.then(() => { Alert.alert('<찜 완료>'); })
setFavorite(true);
}
firebase API : 경로를 잘 참고하자
useEffect(() => {
setTimeout(() => {
setLoading(true);
const DB = firebase_db.ref(`/like/`).on('value', snapshot => (snapshot.val()));
if (DB === null) {
Alert.alert('<찜 없음>', '목록이 없습니다!')
console.log("비어있음!!")
} else {
firebase_db
.ref(`/like/`)
.on('value', (snapshot) => {
const Like_List = Object.values(snapshot.val());
setState(Like_List)
setTotalDataSource(Like_List);
setLoading(false);
console.log(Like_List);
console.log(Like_List.length);
})
}
}, 300)
}, []);
'React-native > 정리' 카테고리의 다른 글
| VirtualizedList 사용하기 (진행중) (0) | 2022.06.07 |
|---|---|
| Pull Down Refresh 구현하기 (0) | 2022.06.07 |
| realtime database 활용하기 (0) | 2022.05.27 |
| Loading화면 구현 (2) (0) | 2022.05.25 |
| Flatlist + SearchBar (3편 공식문서 SearchBar형) (0) | 2022.05.25 |