내가 리액트 쿼리를 공부하는 이유는 두 번째 스터디 주제이기 때문이다.
나는 리액트 쿼리를 아주 살짝 공부 했었다. (코딩애플 선생님 강의)
예전에 공부했을때 리액트 쿼리를 쓰는 이유는 실시간으로 변화하는 값을 빠르게 관리하기 위한 역할을 해준다고 기억하고있다.
이제 본론으로 들어가 리액트 쿼리에 대해 정확하게 공부해보자!
React Query는 React 애플리케이션에서 효율적인 데이터 요청, 캐싱, 상태 관리 등을 단순화하여 개발자가 비동기 작업을 간편하게 처리할 수 있도록 도와주는 라이브러리이다.
리액트 쿼리를 사용하는 이유
// 리액트 쿼리 초기 세팅
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";
const queryClient = new QueryClient();
ReactDOM.render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={true} />
<App />
</QueryClientProvider>
</React.StrictMode>,
document.getElementById("root")
);
import { useQuery } from 'react-query';
const UsersList = () => {
const { data, isLoading, isError } = useQuery('users', fetchUsers);
if (isLoading) {
return <div>Loading...</div>;
}
if (isError) {
return <div>Error occurred while fetching users.</div>;
}
return (
<div>
<h1>User List</h1>
<ul>
{data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};
const fetchUsers = async () => {
const response = await fetch('https://api.example.com/users');
const data = await response.json();
return data;
};
위의 예제에서는 useQuery를 사용하여 users라는 키로 데이터를 가져오고 관리한다.
fetchUsers라는 비동기 함수를 통해 실제 데이터를 가져오는 작업을 수행한다.
useQuery 훅은 data, isLoading, isError와 같은 상태를 반환하여 데이터 로딩 상태와 오류 상태를 처리할 수 있다.
useQuery 를 사용하기 귀찮을때 사용할 수 있다.
useQueries는 promise.all처럼 useQuery를 하나로 묶을 수 있는다. promise.all과 마찬가지로 하나의 배열에 각 쿼리에 대한 상태 값이 객체로 들어온다.
// useQueries 를 이용하여 세 가지 쿼리들을 동시에 처리하는 예제
import { useQueries } from 'react-query';
const UsersList = () => {
const queryConfig = [
{
queryKey: 'users',
queryFn: fetchUsers,
},
{
queryKey: 'products',
queryFn: fetchProducts,
},
{
queryKey: 'orders',
queryFn: fetchOrders,
},
];
const results = useQueries(queryConfig);
return (
<div>
<h1>Data List</h1>
{results.map((result, index) => {
const { isLoading, isError, data } = result;
if (isLoading) {
return <div key={index}>Loading...</div>;
}
if (isError) {
return <div key={index}>Error occurred while fetching data.</div>;
}
return (
<div key={index}>
<h2>{queryConfig[index].queryKey}</h2>
<ul>
{data.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
);
})}
</div>
);
};
const fetchUsers = async () => {
const response = await fetch('https://api.example.com/users');
const data = await response.json();
return data;
};
const fetchProducts = async () => {
const response = await fetch('https://api.example.com/products');
const data = await response.json();
return data;
};
const fetchOrders = async () => {
const response = await fetch('https://api.example.com/orders');
const data = await response.json();
return data;
};
리액트 쿼리의 QueryCache는 데이터를 캐싱하고 관리하는 데 사용되는 중앙 캐시 저장소다.
import { QueryCache, useQueryCache, useQuery } from 'react-query';
const queryCache = new QueryCache();
const UsersList = () => {
const cache = useQueryCache();
const { data, isLoading, isError } = useQuery('users', fetchUsers, {
initialData: cache.getQueryData('users'), // 이전에 캐시된 데이터 사용
initialStale: true, // 쿼리를 처음부터 다시 요청
cacheTime: 60000, // 1분 동안 캐시 유지
});
// 데이터 가져온 후에 캐시 업데이트
if (!isLoading && !isError) {
cache.setQueryData('users', data);
}
if (isLoading) {
return <div>Loading...</div>;
}
if (isError) {
return <div>Error occurred while fetching users.</div>;
}
return (
<div>
<h1>User List</h1>
<ul>
{data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};
const fetchUsers = async () => {
const response = await fetch('https://api.example.com/users');
const data = await response.json();
return data;
};
값을 바꿀때 사용하는 api 이다.
데이터를 post, update 하기위한 api 이다.
리액트 쿼리의 useMutation은 데이터의 생성, 수정 또는 삭제와 같은 변경 작업을 처리하는 데 사용되는 훅이다. 이 훅은 비동기 작업을 처리하고 상태를 관리하여 쉽게 데이터를 변경할 수 있도록 도와준다.
import { useMutation } from 'react-query';
function TodoForm() {
const createTodo = async (data) => {
// 서버로 데이터를 전송하는 비동기 함수
const response = await fetch('/api/todos', {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error('Todo 생성에 실패했습니다.');
}
return response.json();
};
const { mutate, isLoading, isError, error } = useMutation(createTodo);
const handleSubmit = (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const todoData = Object.fromEntries(formData.entries());
mutate(todoData);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" name="title" placeholder="할 일" />
<button type="submit" disabled={isLoading}>
{isLoading ? '로딩 중...' : '추가'}
</button>
{isError && <div>에러: {error.message}</div>}
</form>
);
}
export default TodoForm;
리액트 쿼리의 사용이유와 사용 예제들을 통해 리액트 쿼리와 한층 더 가까워 진 것 같아서 기분이 좋다. ^^ useQuery는 이해가 잘 됐지만 useMutation은 잘 와닿지 않았다...
리액트 쿼리에 대해 공부하면서 "앞으로 리액트 쿼리 공부를 열심히 해야겠다!" 라는 생각이 많이 들었다.
useMutation은 개념만 공부해보고 실습에서 사용해보면서 차차 알아가봅시다.
좋은글이네요 수고했어요!!