# useState vs redux slice vs RTK Query Lorsque vous voulez récupérer ou envoyer des données sur une API REST, plusieurs stratégies s'offrent à vous. Aucune n'est complètement prédominante et elles ont leurs avantages et leurs inconvénients. ## useState + Service Utiliser un useState côté component, créer un service avec Axios et voilà. **Côté Service** ```typescript export class ExampleService { static async findAll() { const response = await axios.get('/api/example'); return response.data; } } ``` **Côté Component** ```typescript export function MonComponent() { const [examples, setExamples] = useState([]); const [isLoading, setIsLoading] = useState(false); const [isError, setIsError] = useState(false); useEffect(() => { async function fetch() { try { setIsLoading(true); const data = await ExampleService.findAll(); setExamples(data); setIsLoading(false); setIsError(false); } catch(error) { setIsLoading(false); setIsError(true); } } fetch(); }); if(isLoading) { return <div>loading...</div> } if(isError) { return <div>There has been a problem, sorry for the inconvenience</div> } return ( <div> {examples.map(item => ...)} </div> ); } ``` ### Avantages * Pur React (pas de library autre qu'axios) * Le plus simple en terme de configuration ### Inconvénients * Peut être assez fastidieux et redondant * Vite chiant si on veut partager le résultat de la requêtes entre plusieurs components ## Redux Slice On fait une slice côté redux, des thunks pour faire les requêtes et on utilise le dispatch et le useSelector côté component **Côté Slice** ```typescript const initialState = { list:[], listLoading:false, listError: null } const exampleSlice = createSlice({ name: 'example', initialState, reducers: { setExamples(state, {payload}) { state.list = payload; state.listLoading = false; state.listError = null; }, listFetch(state) { state.listLoading = true; }, listFetchError(state, {payload}) { state.listLoading = false; state.listError = payload; } } }); export const {setExamples, listFetch, listFetchError} = exampleSlice.actions; export default exampleSlice.reducer; export const fetchExamples = () => async (dispatch) => { try { dispatch(listFetch()); const response = await axios.get('/api/example'); dispatch(setExamples(response.data)); } catch (error) { console.log(error); dispatch(listFetchError(error)); } } ``` **Côté Component** ```typescript export function MonComponent() { const {list, listLoading, listError} = useAppSelector(state.examples); const dispatch = useAppDispatch(); useEffect(() => { dispatch(fetchExamples()); }); if(listLoading) { return <div>loading...</div> } if(listError) { return <div>There has been a problem, sorry for the inconvenience</div> } return ( <div> {list.map(item => ...)} </div> ); } ``` ### Avantages * Utilisation de redux plutôt standard * gestion fine des états (on contrôle tout, vu qu'on fait tout à la main, donc c'est modulable) * Partage des données entre plusieurs components ### Inconvénients * Un peu fastidieux à écrire * Assez redondant entre les différentes requêtes, surtout si comme ici on veut gérer le loading et les erreurs ## RTK Query On crée une api avec RTK Query et côté component, on utilise les méthode qu'il met à disposition **Côté rtk api** ```typescript export const exampleApi = createApi({ reducerPath: 'exampleApi', tagTypes: ['ExampleList'], baseQuery: fetchBaseQuery({baseUrl: process.env.REACT_APP_SERVER_URL +'/api/Example'}), endpoints: (builder) => ({ getAllExamples: builder.query<Example[], void>({ query: () => '/', providesTags: ['ExampleList'] }) }) }); export const {useGetAllExamplesQuery} = exampleApi; ``` **Côté Component** ```typescript export function MonComponent() { const {data, isLoading, isError} = useGetAllExamplesQuery(); if(isLoading) { return <div>loading...</div> } if(isError) { return <div>There has been a problem, sorry for the inconvenience</div> } return ( <div> {data.map(item => ...)} </div> ); } ``` ### Avantages * Le plus rapide à écrire et à utiliser * Plutôt puissant * Permet de gérer pas mal de trucs (loading/pagination/refetch/etc.) * Intégré directement à redux toolkit * Proche d'autres library de query du même type ### Inconvénients * Pas hyper bien documenté (se repose beaucoup sur des exemples de code et d'appli) * Assez jeune, donc pas énormément de réponse sur internet à son propos * Faut apprendre à faire certains trucs dedans qu'on saurait normalement faire sans l'utiliser ## Autre library ? D'autres library de fetching existent, perso je préfère RTK Query du fait qu'il soit complètement intégré à l'environnement Redux Toolkit, mais d'autres sont là depuis plus longtemps (et donc plus utilisées) : * [React Query](https://react-query.tanstack.com/) * [SWR](https://github.com/vercel/swr) ###### tags: `React` `AJAX`