티스토리 뷰
문제
회원이 담은 플레이 리스트의 테이블 형식은 뮤직 아이디를 담은 배열로 되어있고, 음악정보 테이블과 조인으로 음악 데이터를 가져와 현재 플레이리스트를 만들고 있다.
그래서 서버에 등록되어 있는 순서로 자동 정렬 되기 때문에 드래그로 인덱스 순서를 변경하더라도 새로고침 시 다시 서버 데이터를 가져오기 때문에 정렬이 유지되지 않는다는 문제가 있다.
해결방법
- 뮤직 아이디를 담은 배열 형태를 객체로 바꾸는 게 가장 좋은 방법이지만 전체 코드를 수정해야 하기 때문에 서버 데이터의 순서는 그대로 유지하되, 브라우저에서만 인덱스를 변경시키고 유지하도록 zustand와 Local Storage로 해결
- useEffect을 이용해 서버에서 받은 플레이 리스트와 Local Storage에 저장된 플레이리스트의 값이 변경될 때마다 리렌더링이 일어나도록 의존성 배열에 넣어줌
- useEffect내부에서 Local Storage에 저장된 플리가 없으면 서버에서 받아온 데이터를 담음
- Local Storage에 저장된 플레이 리스트와 서버에서 받아오는 플레이리스트의 id값을 비교해 같지 않은 데이터를 추출해 변수에 할당
- 음악이 추가된 경우, 변수랑 Local Storage 저장된 음악 ID를 하나의 배열로 만들어 저장
- 음악이 삭제된 경우, Local Storage 저장된 값을 filter로 서버 데이터와 비교해서 id값이 같은 것만 새 배열로 반환
- 결국 플레이 리스트는 서버 데이터가 아닌, zustand를 이용해 브라우저 localStorage에 저장된 데이터를 사용하게 되므로, 새로고침을 해도 localStorage에 저장된 index순서를 유지할 수 있게 됐다
const customListMusic = useCustomListMusicStore(
(state) => state.customListMusic,
)
const { customListData } = useCustomListMusicStore()
const { customPlayList } = customListData
useEffect(() => {
// 스테이트가 비어있는경우 서버플리 저장
if (customPlayList.length === 0) {
customListMusic(currentPlayList)
return
}
// 디비에서 받아오는 데이터와, 스테이트에 저장한 데이터가 일치하지않은것을 반환
const addValue = currentPlayList.filter((currentItem) => {
return customPlayList.every((customItem) => {
return currentItem.musicId !== customItem.musicId
})
})
const removeValues = customPlayList.filter((currentItem) => {
return currentPlayList.every((customItem) => {
return currentItem.musicId !== customItem.musicId
})
})
// console.log('추가', addValue)
// console.log('삭제', removeValues)
// 디비플리와 스테이트플리가 동일하지않은경우
if (addValue.length > 0) {
// 서버플리가 스테이트 플리보다 많으면, 추가된경우
const addList = [...customPlayList, ...addValue]
customListMusic(addList)
}
if (removeValues.length > 0) {
console.log('삭제되면 스테이트 값도 지워줘야겠지 또도를 생각해')
const currentItems = removeValues.map((item) => {
return item.musicId
})
// 커스텀 플레이 리스트에서 삭제된 아이템 제거
const removeList = customPlayList.filter((item) => {
return !currentItems.includes(item.musicId)
})
customListMusic(removeList)
}
}, [currentPlayList, customPlayList])
// 인덱스 드래그 핸들러
const indexDragHandler = (item: MusicInfoType, index: number) => {
// 드래그 요소를 잡으면 요소의 정보와 인덱스를 스테이트에 저장
setDraggedItem(item)
setDragIndex(index)
}
// console.log('currentPlayList', currentPlayList)
const indexChangeDropHandler = (
dropIndex: number, // 드롭 위치의 인덱스
) => {
// 드래그 요소가 없거나, 현재 리스트가 없으면 반환
if (!draggedItem || !currentPlayList) {
return
}
// 드래그된 요소의 인덱스와 드롭할 인덱스가 동일하지 않으면 실행(기존 인덱스와 동일하면 이동시킬 필요없음)
if (dragIndex !== dropIndex) {
// 드래그된 플리에서 드래드된 인덱스를 삭제
const [draggedMusic] = currentPlayList.splice(dragIndex, 1)
// 드롭한 순간 그 위치에 요소를 삽입
currentPlayList.splice(dropIndex, 0, draggedMusic)
// 변경된 플레이리스트를 로컬스토리지랑 스테이트에 저장
customListMusic(currentPlayList)
}
// 드래그 요소와 인덱스 초기화
setDraggedItem(null)
setDragIndex(-1)
setIsDrag(false)
}
쥬스탄드
type customListMusicStore = {
customListData: {
customPlayList: CurrentPlayListType[]
}
customListMusic: (customPlayList: CurrentPlayListType[]) => void
}
const customListMusicState = {
customListData: {
customPlayList: [],
},
}
export const useCustomListMusicStore = create(
persist<customListMusicStore>(
(set, _) => ({
...customListMusicState,
customListMusic: (customPlayList: CurrentPlayListType[]) => {
set({ customListData: { customPlayList } })
},
}),
{
name: 'customListMusicStore',
},
),
)
'TIL > 최종프로젝트' 카테고리의 다른 글
[최종프로젝트] 플레이 리스트 인덱스 변경 드래그앤 드롭 (세션 저장안됨) (0) | 2024.04.26 |
---|---|
[최종프로젝트] 드래그 앤 드롭 라이브러리 (0) | 2024.04.24 |
[최종프로젝트] 드래그 앤 드롭 플레이리스트 추가 (dataTransfer.setData) (0) | 2024.04.23 |
[최종프로젝트] 재생중인 노래 삭제 시 상태 반영 (0) | 2024.04.18 |
[최종프로젝트] 테일윈드 (tailwind CSS) (0) | 2024.04.16 |