43일차 리액트 심화주차 (React Query)

seul-bean·2023년 10월 15일
0

Today I learned

목록 보기
39/40
post-thumbnail

🍎 React Query

리액트 쿼리(React Query)는 리액트 애플리케이션 데이터 관리를 위한 상태 관리 라이브러리입니다. 리애트 쿼리는 API 호출, 상태 캐싱, 데이터 업데이트 및 동기화, 오류처리 등을 처리하는 간편하고 직관적인 방식을 제공합니다.

🌳 주요 키워드

🌱 Query

어떤 데이터에 대한 요청을 의미.

🌱 Mutation

어떤 데이터를 변경 (추가, 수정, 삭제)

🌱 Query Invalidation

Query를 invalidation. 즉, 무효화 시킨다는 의미.

무효화 시킨다는 것은?
기존에 가져온 Query는 서버 데이터이기 때문에, 언제든지 변경이 있을 수 있음.
그렇기 때문에 '최신 상태가 아닐 수'있다.
→ 기존의 쿼리를 무효화 시킨 후 최신화 시켜야 함.



react-query 설치
yarn add react-query


QueryClientProvider : 데이터를 읽어오는 기능(QueryClient)을 애플리케이션 전체에 주입하도록 하는 API

// App.jsx

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;

🌳 조회 기능

// src>api>todos.js

import axios from "axios";

// 모든 todos를 가져오는 api
const getTodos = async () => {
	const response = await axios.get("http://localhost:3000/todos");
  	return response;
};

export { getTodos };
// Todolist.jsx

import React from "react";

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

function TodoList({ isActive }){
  	// useQuery(Querykey, 비동기 함수)
	const { isLoading, isError, data } = useQuery("todos", getTodos);

	if (isLoading) {
    	return <p>로딩중입니다</p>;
    }
  
  	if (isError) {
    	return <p>오류가 발생하였습니다</p>;
    }
  
  	return (
    	.
      	.
      	.
    )
}

useQuery의 인자에 대해

첫 번째 인자 - Query Keys

  • refetching 하는 데에 쓰인다. (invalidate)
  • 캐싱(caching) 처리를 하는 데에 쓰인다.
  • 애플리케이션 전체 맥락에서 이 쿼리를 공유하는 방법으로 쓰인다.
    (어느 컴포넌트 곳곳에 뿌려져 있어도 같은 key면 같은 쿼리 및 데이터를 보장한다.)
  • 배열의 형태일 수도 있고, nested 객체일 수도 있다.
  • 모든 Query keys는 Unique 해야 한다.

두 번째 인자 - 쿼리 함수

  • 쿼리 함수는 promise 객체를 return 한다.
  • promise 객체는 반드시 data를 resolve하거나 에러를 내야 한다.
    resove는 정상적으로 통신이 되었음을 의미.

useQuery의 결과물 - 객체

  • 시작하면, isLoading이 true가 된다.
  • 조회 결과 오류가 나면 isError가 true가 된다.
    isLoading은 false가 된다.
  • 조회 결과 정상이 되면 isSuccess가 true가 된다.
    isLoading은 false가 된다.

🌳 추가 기능

// src > api > todos.js

import axios from "axios"

// .env를 활용하는게 더 바람직 함
const SERVER_URI = "http://localhost:4000";

const getTodos = async () => {
	const response = await axios.get(`${SERVER_URI}/todos`);
  	return response.data
};

const addTodo = async (newTodo) => {
	await axios.post(`${SERVER_URI}/todos`, newTodo);
}

export {getTodos, addTodo};
// Input.jsx

import { addTodo } from "../../../api/todos";
import { QueryClient, useMutation } from "react-query";

function Input(){
	const queryClient = new QueryClient();
  	
  	const mutation = useMutation(addTodo, {
    	onSuccess: () => {
        	// Invalidate and refresh
          	// todos라는 이름으로 만들었던 query를 invalidate 할 수 있음
          	queryClient.invalidateQueries("todos");
        },
    });
}

invalidate의 과정
Input.jsx에서 값 입력으로 인해 서버 데이터가 변경됨
→ onSuccess가 일어나면 기존의 Query인 "todos"는 무효화
→ 새로운 데이터를 가져와서 "todos"를 최신화시킴
→ TodoList.jsx를 갱신함
따라서 계속해서 리액트 앱은 최신 상태의 서버 데이터를 유지할 수 있게 된다.

무효화라는 뜻이 이해되지 않아서 chatGPT에게 물어본 결과
캐시된 데이터를 무효화(invalidate)시키면, 다음에 해당 데이터를 요청할 때 라이브러리는 새로운 데이터를 가져오게 됩니다. 이것은 캐시된 데이터를 사용하지 않고 서버로부터 새로운 데이터를 다시 요청하는 효과를 가지게 됩니다. 캐시된 데이터를 가져오지 않고 새로운 데이터를 강제로 다시 가져올 수 있습니다.


mutations
query와는 다르게 mutation은 CUD에서 사용된다.

function App() {
	const mutation = useMutation(newTodo => {
    	return axios.post('/todos', newTodo)
    })
    return (
    	<div>
      		{mutation.isLoading ? (
            	'Adding todo...' 
            ) : (
    			<>
     				{mutation.isError?(
                    	<div>An error occurred: {mutation.error.message}</div>
                    ) : null}
					{mutation.isSuccess ? <div>Todo added!</div> : null}
                    <button onClick={()=>{
                    	mutation.mutate({ id: new Date(), title: 'Do Laundry'})
                    }}>
            	        create Todo
                    </button>
				</>
    		)}
      	</div>
    )
}

mutation.mutate(인자)

  • 인자는 반드시 한 개의 변수 또는 객체여야 해요.
  • mutation.mutate(인자1, 인자2) → 오류

결과를 객체(object) 형태로 갖고 있다.
그 결과물 객체는 항상 아래 상태 중 하나에 속한다.

  • isIdle
  • isLoading
  • isError
  • isSuccess
profile
안녕하세요 성장하는 새싹 프론트엔드 개발자 입니다🌱

0개의 댓글