React : React Query + Axios ( 데이터 조회 + 추가 )

728x90
반응형

React Query

1. 기존 미들웨어의 한계 (Redux-Thunk) 보완

: 보일러 플레이트 => 코드량이 너무 많음

: Redux가 비동기 데이터 관리를 위한 전문 라이브러리가 아님

 

2. 강점 

: 사용 방법이 쉽고 직관적임

: 보일러 플레이트 만들다가 오류 날 일이 없음

 

3. 주요 키워드 3가지 

(1) Query

: 데이터 물어보기

: axios의 get요청과 유사 

 

(2) Mutation

: 어떤 데이터 변경

: CRUD 중 CUD에 해당

: axios의 post,patch,delete와 유사

 

(3) Query Invalidation (★)

: 위에서 본 쿼리를 인벨리데이션한다 = 무효화 시킨다.

: 저녁 8시의 데이터와 저녁 9시의 데이터는 일치하지 않음 => 무효화시키고 => 9시의 데이터를 가져와야함 (최신상태)

 

★ 정리

1) 쿼리 키 : refecthing하는데 쓰임 = invalidate (무효화)

=> 애플리케이션 전체 맥락에서 이 쿼리를 공유하는 방법으로 사용 

=> Unique 해야함! (형태는 다양하게 사용됨)

 

* 배열 : 순서 중요 / 객체:  순서 안 중요

 

2) 쿼리 함수 : 비동기함수여서 promise를 리턴함

* 비동기함수는 반드시 data를 resolve (정상 작동)하거나 error 발생시켜야함

* try ~ catch로 꼭 작성

 

3) useQuery 결과물 : 객체!

=> isLoading, isError, data 등이 있음 (구조분해할당으로 사용했음)

 

4) mutation : 변경

=> CUD 에서만 사용!

=> 쿼리 인벨리데이션 꼭 기억 + 사용방법 숙지 

=> 인자 (비동기함수)

=> useMutation은 hook임 = 함수 = API

=> mutation.mutate(인자) =결과 {객체}

: 인자 = 반드시 한개의 변수 또는 객체

mutation.mutate(인자1,인자2)==> 오류

=> onSucess가 일어났을때, 반드시 해당 쿼리키를 invalidateQuery 해야함

 

 

 

4. 리액트 쿼리 적용

(0) 기존 리액트 청크 : dispatch + useSelector를 사용해서 데이터 불러옴

(1) 리액트 쿼리  패키지 설치

yarn add react-query

(2) 프로젝트를 아우르는 상위 컴포넌트에서 세팅 => index.tsx

import React from 'react';
import Router from './shared/Router';
import { QueryClient, QueryClientProvider } from 'react-query';

const queryClient = new QueryClient();

const App = () => {
    return (
        <QueryClientProvider client={queryClient}>
            <Router />
        </QueryClientProvider>
    );
};

export default App;
 
(3) [.env] 파일
REACT_APP_SERVER_URL = http://localhost:4000

* REACT_APP 어두 필수로 사용해야함

*해당 오류:  env 설정 후 yarn start 재실행하면 해결됨

 

 

[조회]

 

(3-1) src > [api.ts]

// axios 요청이 들어가는 모든 모듈
import axios from 'axios';

//조회
const getTodos = async () => {
    const response = await axios.get(`${process.env.REACT_APP_SERVER_URL}/todos`);
    return response.data;
};

export { getTodos };

 

(3-2) TodoList.jsx

import { getTodos } from '../../../api/todos';
import { useQuery } from 'react-query';

 
function TodoList({ isActive }) {
    //const todos = useSelector((state) => state.todos); //리덕스 방법

    //쿼리방법 : 결과값 {구조분해할당} = useQuery ("쿼리이름",조회하는 비동기함수)
    //쿼리: isLoading, isError, data 제공 해줌 => 제공 받기 위해서는 비동기함수에서 (getTodos) return 필수
    const { isLoading, isError, data } = useQuery('todos', getTodos);

    //쿼리가 미완료시 isLoading = true
    if (isLoading) {
        return <h1>로딩중입니다.</h1>;
    }

    //쿼리 오류 발생시
    if (isError) {
        return <h1>오류가 발생하였습니다.</h1>;
    }

    return (
        <StyledDiv>
            <StyledTodoListHeader>{isActive ? '해야 할 일 ⛱' : '완료한 일 ✅'}</StyledTodoListHeader>
            <StyledTodoListBox>
                {data
                    .filter((item) => item.isDone === !isActive)
                    .map((item) => {
                        return <Todo key={item.id} todo={item} isActive={isActive} />;
                    })}
            </StyledTodoListBox>
        </StyledDiv>
    );
}

export default TodoList;

1) 기존 리덕스 방법 : useSelector 사용

2) 쿼리 : isLoading, isError, data 값 모두 제공 => 구조분해할당하여 필요 데이터 사용 가능

3) useQuery("쿼리이름, 조회 비동기함수) --> 비동기함수(getTodos)는 return 필수로 해줘야함

 

[추가]

(3-1) src > [api.ts]

// axios 요청이 들어가는 모든 모듈
import axios from 'axios';
 

//추가
//인자 : 새로 추가하는 데이터 newTodo
const addTodos = async (newTodo) => {
    await axios.post(`${process.env.REACT_APP_SERVER_URL}/todos`, newTodo);
};

export { getTodos, addTodos };

1) 새로 추가할 데이터를 인자로 받아야함 = newTodo

 

(3-2) Input.jsx

function Input() {
    const dispatch = useDispatch();

    //리액트 쿼리 관련 코드
    const queryClient = useQueryClient();

    //변경 => mutation
    const mutation = useMutation(addTodos, {
        onSuccess: () => {
            queryClient.invalidateQueries('todos쿼리키');
        },
    });
 
//새 데이터 클릭이벤트 쪽
       //api인자를 넣어두면 됨= 새로운 데이터
        mutation.mutate(newTodo);

1) App.jsx 에서 const queryClient = new QueryClient(); 

여기서는 useQueryClient 사용해야함--> 상위컴포넌트에서 만든것을 하위에서 이용해서 사용 가능

 

2) 변경 (mutation)

useMutation(만들어놓은 api, 객체 {성공했을때, 실패했을때}) 

 

3) invalidateQueries

어떤걸 인벨리데이트 할거냐 => todos쿼리키 

=> 무효화시키고 다시 가져옴 

=> todos 이름을 가진 쿼리를 다시 실행하겠다 

=> 바로 리프레시가능

 

4) 새로운 데이터 추가 

mutation.mutate(새로 추가할 데이터)

 

 

끝.

 

 

반응형