기록을 불러오는 중입니다...
useQuery 내부 구현을 보면, 쿼리 클라이언트와 옵저버를 이용하는 커스텀 훅임을 알 수 있습니다.// 여기서는 글 목록만!
function PostList() {
const { data: postList } = useQuery({
queryKey: ['post'],
queryFn: fetchPostList,
});
}
// 여기서는 글만!
function Post(props) {
const { id, img } = props;
const { data: post } = useQuery({
queryKey: ['Post', id],
queryFn: fetchPost,
});
}function useBaseQuery(...) {
// Handle suspense
if (shouldSuspend(defaultedOptions, result)) {
throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary)
}
}QueryClientProvider 를 통해, 리액트 컴포넌트 트리 내에서 손쉽게 QueryClient 를 공유할 수 있습니다. 물론, 이 또한 React 내장 Context API를 이용해 만들어져있습니다.initialData 내부에서 getQueryData 를 사용하여, 화면의 깜빡거림을 방지하는 기술을 보여주고 있습니다.type State = 'all' | 'open' | 'done';
type Todo = {
id: number
state: State
};
type Todos = ReadonlyArray<Todo>;
const fetchTodos = async (state: State): Promise<Todos> => {
const response = await axios.get(`todos/${state}`)
return response.data
};
const useTodosQuery = (state: State) =>
useQuery({
queryKey: ['todos', state],
queryFn: () => fetchTodos(state),
initialData: () => {
const allTodos = queryClient.getQueryData<Todos>([
'todos',
'all',
])
const filteredData =
allTodos?.filter((todo) => todo.state === state) ?? []
return filteredData.length > 0 ? filteredData : undefined
},
}); const App = () => {
const { data } = useQuery({
queryKey: ['key'],
queryFn,
staleTime: Infinity,
})
return data ? <MyForm initialData={data} /> : null
}
const MyForm = ({ initialData }) => {
const [data, setData] = React.useState(initialData)
...
}staleTime 을 Infinity 로 설정해주는 것을 잊지 마세요!setQueryData 를 이용해 쿼리 데이터를 변경하는 것은 일반적으로 낙관적 업데이트 혹은 서버 상태를 받아온 직후에만 사용하기를 권장하고 있습니다.// 2번에 나온 예제 코드
const useTodosQuery = (state: State) =>
useQuery({
queryKey: ['todos', state],
queryFn: () => fetchTodos(state),
});// 패치 함수 내에서 서버 상태를 변형하는 경우
const fetchTodos = async (): Promise<Todos> => {
const response = await axios.get('todos')
const data: Todos = response.data
return data.map((todo) => todo.name.toUpperCase())
};
const useTodosQuery = () =>
useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
});select 옵션이 좋은 해결책이 됩니다. 이는 온전히 클라이언트 사이드에서 변형 로직을 최적화하기 좋은 곳입니다.useCallback 을 이용해서 메모이징을 하는 것을 권장합니다.// select 옵션을 이용해 서버 상태를 변형하는 경우
const useTodosQuery = (select) =>
useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
select,
});
const useTodosCount = () => useTodosQuery((data) => data.length);
const useTodo = (id) => useTodosQuery((data) => data.find((todo) => todo.id === id));