Giả sử ta cần xây dựng một ứng dụng lấy dữ liệu từ PokeAPI.
Trước tiên, ta cần import hàm createApi từ Redux Toolkit thông qua hai entry point sau:
import { createApi } from "@reduxjs/toolkit/query"
/* React-specific entry point that automatically generates
hooks corresponding to the defined endpoints */
import { createApi } from "@reduxjs/toolkit/query/react"Entry point thứ 2 cho phép tạo ra các hook để dùng trong các functional component.
Setting up
Create an API Slice
Tạo ra một API slice thông qua createApi như sau:
// services/pokemon.js
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"
export const pokemonApi = createApi({
reducerPath: "pokemonApi",
baseQuery: fetchBaseQuery({ baseUrl: "https://pokeapi.co/api/v2/" }),
endpoints: (builder) => ({
getPokemonByName: builder.query({
query: (name) => `pokemon/${name}`,
}),
}),
})Đối số của createApi bao gồm:
reducerPath: tên của reducer để cấu hình store.baseQuery: chỉ định base URL của API.endpoints: là một callback có đối số là một object bao gồm các endpoint được sử dụng ở trong ứng dụng.
Mỗi endpoint truyền vào sẽ được RTK Query tạo ra một hook tương ứng ở trong API slice trả về của createApi. Ví dụ, nếu endpoint có tên là getPokemonByName thì hook của nó sẽ là useGetPokemonByNameQuery.
Ta export hook này ra để sử dụng ở component như sau:
export const { useGetPokemonByNameQuery } = pokemonApiAdd the Service to Your Store
Ngoài hook trên, API slice còn có một slice reducer và một custom middleware giúp xử lý việc lấy dữ liệu. Hai thành phần này cần phải được thêm vào store như sau:
// app/store.js
import { configureStore } from "@reduxjs/toolkit"
import { pokemonApi } from "../services/pokemon"
export const store = configureStore({
reducer: {
[pokemonApi.reducerPath]: pokemonApi.reducer,
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(pokemonApi.middleware),
})Wrap Your Application with the Provider
Tất nhiên, ta cũng cần phải cung cấp store cho các component tương tự như khi sử dụng Redux thông thường:
// Existing import ...
import { Provider } from "react-redux"
import { store } from "./app/store.js"
const root = createRoot(document.getElementById("root"))
root.render(
<StrictMode>
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
)Using the Query
Gọi sử dụng hook của API slice ở trong component như sau:
// features/pokemon/Pokemon.jsx
import { useGetPokemonByNameQuery } from "../../services/pokemon"
export default function Pokemon() {
const { data, error, isLoading } = useGetPokemonByNameQuery("pikachu")
return (
<div>
{error ? (
<p>Oh no, there was an error</p>
) : isLoading ? (
<p>Loading...</p>
) : data ? (
<div>
<h3>{data.species.name}</h3>
<img
src={data.sprites.front_shiny}
alt={data.species.name}
/>
</div>
) : null}
</div>
)Hook useGetPokemonByNameQuery trả về một đối tượng gồm nhiều thuộc tính. Trong đó:
datachính là dữ liệu nhận được từ API.errorlà lỗi của request.isLoadinglà một biến boolean cho biết request đang được load.
RTK Query sẽ:
- Tự động fetch dữ liệu khi component được mount.
- Re-fetch khi đối số truyền vào hook bị thay đổi.
- Re-render component khi state bị thay đổi.