JoungSik/React-Query

Created Sun, 10 Oct 2021 20:12:15 +0900 Modified Sat, 31 Dec 2022 01:31:35 +0900

React-Query

기존에는 Redux 를 사용해서 전역관리를 하고 있었습니다.

그러던 중 사이드 프로젝트에서 Redux 를 사용해서 코드를 작성하려니 굉장히 많은 보일러 플레이트 코드를 작성하는게 아찔하게 느껴지더라고요..

하라면 하겠지만 즐겁게 하고 싶었던 사이드 프로젝트에서 그러고 싶진 않아서 평소 관심이 있던 React-Query 를 사용하기로 했습니다.

설치

Getting Started 기준으로 진행합니다.

yarn add react-query

QueryClientProvider 로 리엑트 앱을 감싸줍니다.

import React from 'react';
import { QueryClient, QueryClientProvider } from 'react-query';
import { ChakraProvider } from '@chakra-ui/react'
import Routers from './routes';
import theme from './utils/theme';

const queryClient = new QueryClient();

const App = () => {
  return (
    <QueryClientProvider client={queryClient}>
      <ChakraProvider theme={theme}>
        <Routers />
      </ChakraProvider>
    </QueryClientProvider>
  )
};

export default App;

디버깅 툴을 붙여줍니다.

import React from 'react';
import { QueryClient, QueryClientProvider } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools'; // 추가 코드
import { ChakraProvider } from '@chakra-ui/react'
import Routers from './routes';
import theme from './utils/theme';

const queryClient = new QueryClient();

const App = () => {
  return (
    <QueryClientProvider client={queryClient}>
      <ChakraProvider theme={theme}>
        <Routers />
      </ChakraProvider>
      <ReactQueryDevtools initialIsOpen={false} /> {/* 추가 코드 */}
    </QueryClientProvider>
  )
};

export default App;

그러면 하단에 이렇게 아이콘이 뜨는데 클릭하면 디버깅 툴이 뜹니다.

1

2

네트워크 통신을 위해 axios 를 설치합니다.

yarn add axios

사용

사용하려고 했던 로그인 로직을 예제를 참고해 login.tsx 에 구현해봅니다.

먼저 다음 링크를 참고한 axios 설정을 합니다.

src/api/index.ts

import axios, { AxiosResponse } from 'axios';
import { UserType } from '../models/user.interface';

const baseUrl = process.env.SERVER_URL || 'http://localhost:3000/';

const instance = axios.create({
  baseURL: baseUrl,
  timeout: 15000,
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
  }
});

const authInstance = (jwt: string) => axios.create({
  baseURL: baseUrl,
  timeout: 15000,
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'Authorization': jwt
  }
});

const responseBody = (response: AxiosResponse<{}>) => response;

export const requests = {
  get: (url: string, jwt: string) => authInstance(jwt).get(url).then(responseBody),
  post: (url: string, body: {}, jwt: string) => authInstance(jwt).post(url, body).then(responseBody),
  patch: (url: string, body: {}, jwt: string) => authInstance(jwt).put(url, body).then(responseBody),
  delete: (url: string, jwt: string) => authInstance(jwt).delete(url).then(responseBody),
};

export const User = {
  login: (user: UserType) => instance.post('login', user)
}

src/models/user.interface.ts

export interface UserType {
  id?: number;
  name?: string;
  email: string;
  password?: string;
  authorization?: string;
}

로그인, 회원가입 API 의 경우에는 Authorization 을 필요로 하지 않기 때문에 index.ts 안에서 작성했고 그 외의 API 들은 Authorization 이 필요해 외부에 작성할 예정 입니다.

이제 로그인 API 를 적용해 봅시다.

const queryClient = useQueryClient();

const mutation = useMutation(
  userinfo => User.login({ email: userinfo.email, password: userinfo.password }), {
    onMutate: async (user: UserType) => {
      const previousTodos = queryClient.getQueryData<UserType>('user');
      return { previousTodos };
    },
    onSuccess: (response, variables, context) => {
      console.log(response.headers);
      queryClient.setQueryData<UserType>('user', response.data);
    },
    onError: (err, variables, context) => {
      if (context?.previousTodos) {
        queryClient.setQueryData<UserType>('user', context.previousTodos);
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries('user')
    },
  });

useEffect(() => {
  mutation.mutate({ email: 'tjstlr2010@gmail.com', password: 'qwer1234' });
}, []);

3

결과 값 리턴이 재대로 되는걸 확인 할 수 있었지만 CORS 가 터졌습니다 ㅋㅋㅋㅋ

CORS 수정 후 인증 값이 저장 됩니다.

4