이전에 유저별 등록 게임 모달을 만들면서 유저별로 등록한 게임을 다루면서 유저가 직접 게임의 우선순위를 부여할 수 있게 하기 위해서 react-beautiful-dnd
라이브러리를 사용해서 직접 조정할 수 있게 만들었었다.
서버와의 연결을 해서 유저가 등록한 게임을 []
로 받아온 상황. 여기서 헷갈렸던 것이 useQuery
를 통해 받아오는 data
를 직접 수정해도 되는지였다. 오늘 작업을 하기 전부터 기대 반 걱정 반이었는데, 결론부터 말하자면 수정이 가능하다!! 하지만! 그렇게 하면 데이터의 불변성을 지킬 수 없다.
우선 불변성을 고려하지 않은 코딩이다. 이렇게해도 작동은 한다. 어떤 side effect가 생길지 몰라서 걱정되는 것 뿐...
먼저 서버에서 필요한 데이터를 받아왔다.
const { data, isFetching, isLoading, isError } = useQuery(
['game-account-list'],
async () => {
const result = await axiosInstance.get('게임리스트api');
console.log(result);
return result;
},
{
refetchOnWindowFocus: false,
refetchOnMount: true,
refetchOnReconnect: true,
retry: 2,
initialData: [],
keepPreviousData: true,
},
);
여기서 받아온 데이터를 직접 dnd
에서 수정했다.
const reorder = (list, startIdx, endIdx) => {
const result = Array.from(list);
const [removed] = result.splice(startIdx, 1);
result.splice(endIdx, 0, removed);
return result;
};
const Component = () => {
...
/* 선택한 태그 드래그 앤 드롭 */
// 드래그 끝나면 할 일
const onDragEnd = result => {
// source : 현재 위치한 droppable의 위치, 인덱스
// destination : dnd를 마친 후 droppable의 위치, 인덱스
// 바깥으로 drop 시에
if (!result.destination) {
return;
}
// 같은 자리에 가져다 두었다면 그냥 리턴
if (result.destination.index === result.source.index) {
return;
}
const items = reorder(
data.data,
result.source.index,
result.destination.index,
);
if (data) data.data = items; // 새로운 것 옮겨두고.
// 이렇게 data.data에다가 직접적으로 수정해주었다.
};
...
}
이 상태에서 수정한 data.data를 저장하는 버튼을 만들었다. 이건 react-query의 useMutation으로.
const gameListMutate = useMutation((items)=>{
return axiosInstance.put('게임리스트api', items);
})
// 제출 시에 일어나는 logic
const onGameEnrollmentOrderSubmit = () => {
// mutate - 일단은 바로바로 저장됨. 저장버튼 눌러야 되는 걸로 변경??
gameListMutate.mutate(data.data, {
onSuccess: () => {
closeModal();
return queryClient.invalidateQueries(['game-account-list']); // 이전에도 적었다시피 return을 해주면 closeModal하고 일어난다!
},
onError: err => {
console.log(err);
},
});
};
이와 관련된 논의가 react-query
라이브러리에서 있었다.
https://github.com/tannerlinsley/react-query/discussions/1304
만약 useQuery
에서 받아온 data를 위와 같은 방법으로 직접 수정하면 어떻게 될까? 캐싱된 데이터에 영향을 끼치게 된다.
react-beautiful-dnd
를 사용해서 드래그 앤 드랍했을 때, 캐싱된 데이터가 바뀐 것을 확인할 수 있다. https://github.com/tannerlinsley/react-query/discussions/530
받아온 data를 useMemo를 이용해서 새로운 변수에다가 집어넣으라는 답변이 있었다.
https://tkdodo.eu/blog/react-query-data-transformations
react-query
의 contributor 중 한 명인 TkDodo 님의 블로그에도 이와 관련된 포스팅이 있었다.
react에서는 항상 데이터의 불변성을 유지해주어야 한다는 사실 잊지 말자!
react-query
, react-beautiful-dnd
라이브러리