# 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`