Just Do IT!

useContext 사용해서 전역에서 유저 정보 가져오기 본문

개발 공부/React

useContext 사용해서 전역에서 유저 정보 가져오기

MOON달 2024. 10. 31. 11:29
728x90
반응형

이번 프로젝트에서는 소셜 로그인이 있기 때문에 쿠키에서 id를 받아와서 로그인 여부를 판단하고 있다.

그런데 한 가지 문제점이 생겼다.

header에 유저 정보를 가져와야 한다 (유저 프로필)

문제집/스터디 페이지에서 유저 정보를 가져와서 생성한 사람과 비교해야 한다.

 

이런 문제점이 생기는데 콘솔에 찍어보면 쿠키를 통해 가져올 수 있는 정보는 id밖에 없기 때문에

백엔드 response, request를 아예 갈아엎어야 하던지 아니면 쿠키에 username을 받아와야 했다.

그런데 쿠키에 username을 받아오지 않고 id로만 받아와야만 했기 때문에 (username이 unique key가 아님)

그냥 프론트쪽에서 전역적으로 유저 정보를 받아와서 사용할 수 있도록 했다.

 

 

 

 

 

 

 

 

useContext?

react는 부모 컴포넌트 (최상위 App)와 자식 컴포넌트로 이루어진 트리 구조를 가지고 있다.

props를 전달할 때는 부모 컴포넌트에서 자식 컴포넌트로 단계별로 전달하게 되는데, 전달해야 될 컴포넌트와 거리가 멀어지면 코드가 복잡해진다.

그리고 만약 부모 컴포넌트에서 필요한 컴포넌트까지 계속해 data를 넘겨줘야 할 때 props를 통해 넘겨주게 되는데 이렇게 된다면 props drilling이 일어난다. 이걸 극복하기 위한 것이 context 개념이다.

 

 React context를 활용하면 props로 하나하나 data를 넘겨주지 않아도 전역 데이터를 쉽게 공유하고 관리할 수 있다.

 

 

 

 

 

 

useContext 사용법

1. useContext 생성 및 export 하기

const UserContext = createContext();

export const UserProvider = ({ children }) => {
  const token = getCookie("accessToken");
  const userId = token ? JSON.parse(atob(token.split(".")[1])).sub : null;

  const {
    data: userInfo,
    isLoading,
    isError,
  } = useQuery({
    queryKey: ["userInfo", userId],
    queryFn: async () => {
      if (!userId) return null;
      try {
        const response = await api.get(`/mypage/profile`);
        return response.data;
      } catch (error) {
        console.error("Error fetching user info: ", error);
        throw error;
      }
    },
    enabled: !!token && !!userId,
  });

  return (
    <UserContext.Provider value={{ userInfo, isLoading, isError }}>
      {children}
    </UserContext.Provider>
  );
};

export const useUser = () => useContext(UserContext);

 

createContext를 import 하고, createContext로 return 받은 변수를 export 해준다.

 

여기서는 유저 정보를 가져와서 전역적으로 사용해야 했기에 api를 통해 유저 정보를 가져오고

그 value를 전역적으로 적용해주었다.

 

 

 2. Context 태그로 컴포넌트를 감싸고, value에 공유할 데이터값 작성하기

최상위 컴포넌트인 App에서 감싸줘야 전역적으로 사용할 수 있기에 App.jsx 파일에서 컴포넌트를 감싸주었다.

그런데 현재 내가 진행하는 프로젝트에서 react query를 사용하고 있어서 그 하단에 추가해주었다.

 

  <QueryClientProvider client={queryClient}>
    <UserProvider>
      <App />
    </UserProvider>
  </QueryClientProvider>

 

3. 사용 예시

const BookPageWithQuestion = () => {
  const { id } = useParams();
  const { userInfo, isLoading, isError } = useUser();

  // 로딩 및 에러 상태 처리
  if (isLoading) return <div>Loading...</div>;
  if (isError) return <div>Error loading user info.</div>;

  const currentUserName = userInfo ? userInfo.userName : null;

  return (
    <>
      <BookInfo bookId={id} currentUserName={currentUserName} />
    </>
  );
};

 

사용하는 예시이다.

여기서 currentUserName이란 현재 로그인한 사용자의 이름을 뜻한다.

이 로그인한 사용자와, 문제집/스터디를 만든 username과 비교해야 하기 때문에 useUser를 통해 쉽게 불러올 수 있었다.

 

 

 

 

 

 

 

 

 

 


인증 관련해서 context를 만든 적이 있었는데, 그거랑 지금 적용한 부분은 좀 다른것 같다.

api를 전역적으로 불러오면 속도가 좀 느려지지 않을까 걱정되는데 그건 나중에 배포 뒤에 시간이 있으면 고민해볼 예정이다.

 

이번에 프로젝트를 하면서 정말 많이 배운다.

728x90