이전에 작성했던 로직은 도시 이름 데이터를 게임 스케줄 데이터에서 가져오는게 아니라, 별도로 관리해주고 있었기 때문에 로직 수정이 필요했다.
이 때 여러 비동기 작업을 병렬로 처리하기 위해 Promise.all을 사용하는 로직도 있었지만 아직 사용법이 익숙하지 않아 for...of를 사용하여 배열을 순회하며 원하는 값을 넣어주는 로직을 사용하기로 했다.
export const fetchWithWeatherData = async (gameScheduleData) => {
const results = [];
for (const game of gameScheduleData) {
try {
const location = game.location.includes('-')
? game.location.split('-', 1)
: game.location;
const weather = await fetchWeatherData(location);
results.push({ ...game, weather: weather.weather[0].main });
} catch (error) {
console.error(`Error fetching weather data for ${game.location}:`, error);
}
}
return results;
};
같은 컴포넌트에 fetchWithWeatherData()
함수를 사용해줬다면 리렌더링을 방지하기 위해 useCallback으로 감싸줬겠지만 유지보수 및 재사용을 위해 함수를 별도의 파일에 분리해줬고, 따라서 useEffect안에서 함수를 사용해 마찬가지로 관련 상태가 업데이트 될 때만 함수가 실행하여 원하는 데이터를 받을 수 있도록 해줬다.
useEffect(() => {
const fetchWeatherForGames = async () => {
if (isGameScheduleSuccess) {
try {
const mergedData = await fetchWithWeatherData(gameScheduleData);
setGameInfo(mergedData);
} catch (error) {
console.error('Error fetching weather data:', error);
}
}
};
fetchWeatherForGames();
}, [isGameScheduleSuccess, gameScheduleData]);
이 때 처음에 page_id를 깜박하고 테이블에 만들어두지 않아 이후에 추가로 만들어 Foreign Keys에 연결해줬다.
import supabase from '../supabase/supabaseClient';
export const getComments = async () => {
try {
const { data, error } = await supabase.from('comments').select('*');
if (error) {
throw error;
}
return data;
} catch (error) {
console.error('Failed to get comment:', error.message);
throw new Error(`Failed to get comment : ${error.message}`);
}
};
export const addComments = async (comment) => {
try {
const { body, created_at, id, page_id } = comment;
if (!body) {
throw new Error('Body text are required');
}
const { data, error } = await supabase
.from('comments')
.insert([
{ body: body, id: id, created_at: created_at, page_id: page_id },
]);
if (error) {
throw error;
}
return data;
} catch (error) {
throw new Error(`Failed to add comment: ${error.message}`);
}
};
이전에 input 값 상태관리 시 리렌더링을 방지하기 위해 useRef를 사용하는게 더 좋다는 튜터님의 피드백을 받고 이번에는 useState대신 useRef를 사용해서 동적으로 상태를 관리할 수 있도록 했다.
Tanstack Query를 사용하면서 다른 라이브러리를 사용해 별도로 상태관리를 해줄 필요가 없어 굉장히 효율적으로 데이터 상태관리를 할 수 있다.
const Comment = () => {
const commentRef = useRef(null);
const queryClient = useQueryClient();
const param = useParams();
const pageId = param.id;
const {
data: comments,
isPending,
isSuccess,
} = useQuery({
queryKey: ['comments',pageId],
queryFn: getComments,
});
const mutationAdd = useMutation({
mutationFn: addComments,
onSuccess: () => {
queryClient.invalidateQueries(['comments']);
},
});
const handleSubmitComment = (event) => {
event.preventDefault();
const commentBody = commentRef.current.value;
const newComment = {
id: uuid4(),
body: commentBody,
created_at: new Date().toISOString(),
page_id: pageId,
};
if (isSuccess) {
console.log('newComment => ', newComment);
mutationAdd.mutate(newComment);
commentRef.current.value = '';
}
};
if (isSuccess) {
console.log('comments => ', comments);
}
return (
<div className="flex flex-col bg-darkgray w-full h-[50%] rounded-2xl p-9 gap-3">
<p className="text-xl">한 줄 응원하기</p>
<form
className="flex gap-3 w-full h-[10%] justify-between items-center gap-1 text-darkgray"
onSubmit={handleSubmitComment}
>
<input
type="text"
placeholder="우리팀 화이팅!!!"
className="p-2 rounded-md w-[100%] h-full focus:outline-none"
ref={commentRef}
/>
<button
type="submit"
className="rounded-md bg-white px-4 py-2 min-w-[110px] h-full inline-block hover:bg-[#3D69CB] hover:text-white"
>
작성하기
</button>
</form>
<ul className="grid auto-rows-[10%] gap-1 p-3 bg-white text-darkgray h-[100%] rounded-md overflow-y-auto">
{isPending && <div>댓글이 로딩중입니다...</div>}
{isSuccess &&
comments.map((comment, index) => {
if (comment['page_id'] == pageId) {
const date = comment.created_at.split('.', 1)[0].split('T', 2)[0];
const time = comment.created_at.split('.', 1)[0].split('T', 2)[1];
return (
<li className="flex justify-between p-2" key={index}>
<span>{comment.body}</span>
<span>{date + ' ' + time}</span>
</li>
);
} else {
return null;
}
})}
</ul>
</div>
);
};
export default Comment;