๋ฐ๋ก ๊ฐ๊ธฐ : https://light9639.github.io/RTK-Query-TypeScript/
โจ ๐ช Redux-Toolkit-Query๋ฅผ ์ด์ฉํ ์์ ํ์ผ. โจ
- React ์์ฑ
npm create-react-app my-app
# or
yarn create react-app my-app
- vite๋ฅผ ์ด์ฉํ์ฌ ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ ค๋ฉด
npm create vite@latest
# or
yarn create vite
- ํฐ๋ฏธ๋์์ ์คํ ํ ํ๋ก์ ํธ ์ด๋ฆ ๋ง๋ ํ React ์ ํ, Typescirpt-SWC ์ ํํ๋ฉด ์์ฑ ์๋ฃ.
- Redux-Toolkit ์ค์น ๋ช ๋ น์ด
npm install redux react-redux @reduxjs/toolkit
# or
yarn add redux react-redux @reduxjs/toolkit
map
๋ฐ๋ณต๋ฌธ์ผ๋ก ๋ฐ์ดํฐ ์ค ์ผ๋ถ๋ฅผ ๊ฐ์ ธ์ ํ๋ฉด์ ์์ฑํ๋ค.select
์onChange
ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ช์ด๋ง๋ค ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ์ง๋ฅผ ์ ํ ์ ์๋ค.
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import './App.css'
import Pokemon from './Pokemon'
const pokemon = ['bulbasaur', 'pikachu', 'ditto', 'bulbasaur']
export default function App() {
const [pollingInterval, setPollingInterval] = useState<number>(0)
return (
<div className="App">
<div>
<a href="https://ko.redux.js.org/introduction/getting-started/" target="_blank" rel="noreferrer">
<img src="https://camo.githubusercontent.com/7b7f04b16cc2d2d4a32985710e4d640985337a32bbb1e60cdacede2c8a4ae57b/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f72656475782e737667" className="logo" alt="Vite logo" />
</a>
<a href="https://reactjs.org" target="_blank" rel="noreferrer">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Redux-Toolkit-Query</h1>
<select
onChange={(change) => setPollingInterval(Number(change.target.value))}
>
<option value={0}>Off</option>
<option value={1000}>1s</option>
<option value={5000}>5s</option>
</select>
<div className='Content_Wrapper'>
{pokemon.map((poke, index) => (
<Pokemon key={index} name={poke} pollingInterval={pollingInterval} />
))}
</div>
</div>
)
}
ApiProvider
๋ ๋ฆฌ๋์ค์ฟผ๋ฆฌ์์pokemonApi
๋pokemon.ts
์์import
ํ ๋ค์<App />
์ ๊ฐ์ธ๋ฉด ๋ฆฌ๋์ค ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์๋ค
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
import { ApiProvider } from '@reduxjs/toolkit/query/react'
import { pokemonApi } from './services/pokemon'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<ApiProvider api={pokemonApi}>
<App />
</ApiProvider>
</React.StrictMode>,
)
useGetPokemonByNameQuery
๋ฅผ ์ฌ์ฉํ์ฌ ๋ก๋ฉ์ค์ผ ๋ ์๋ฌ๊ฐ ๋ฌ์ ๋ ํ๋ฉด์ ํ์ํ ์ ์๋ค.
import { useGetPokemonByNameQuery } from './services/pokemon'
import React from 'react'
interface PokeType {
name: string
pollingInterval: number
}
export default function Pokemon({ name, pollingInterval }: PokeType): JSX.Element {
const { data, error, isLoading, isFetching } = useGetPokemonByNameQuery(name, { pollingInterval })
if (error) return (<>Oh no, there was an error</>)
if (isLoading) return (<>Loading...</>)
return (
<div className='Content_Box'>
<h3>
{data.species.name} {isFetching ? '...' : ''}
</h3>
<img src={data.sprites.front_shiny} alt={data.species.name} />
</div>
)
}
createApi
,fetchBaseQuery
๋ฅผimport
ํ ๋ค์pokemonApi
๋ฅผuseGetPokemonByNameQuery
๋ก ๋ด๋ณด๋ด ์ฌ์ฉํ๋ค.
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
export const pokemonApi = createApi({
reducerPath: 'pokemonApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
tagTypes: [],
endpoints: (builder) => ({
getPokemonByName: builder.query({
query: (name: string) => `pokemon/${name}`,
}),
}),
})
// ์ฌ์ฉํ hook๋ฅผ ๋ด๋ณด๋ด๊ธฐ
export const { useGetPokemonByNameQuery } = pokemonApi