[Team Project] 아웃소싱 프로젝트 (3)

liinyeye·2024년 6월 19일
0

Project

목록 보기
21/44
post-thumbnail

게임 스케줄에 따른 날씨 데이터 병합

이전에 작성했던 로직은 도시 이름 데이터를 게임 스케줄 데이터에서 가져오는게 아니라, 별도로 관리해주고 있었기 때문에 로직 수정이 필요했다.

게임 스케줄 데이터에 있는 도시 이름에 따라 날씨 데이터 가져오기

이 때 여러 비동기 작업을 병렬로 처리하기 위해 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}`);
  }
};

Tanstack Query를 사용한 댓글 상태관리

이전에 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;
profile
웹 프론트엔드 UXUI

0개의 댓글