Bonjour,

J'aimerais avoir de l'aide sur mon code.

Ce que je veux

Je souhaite rediriger l'utilisateur avec React Router, une fois que j'ai reçu une réponse de succès, venant de mon API Rest. Cette requête API Rest, je les déclenché après le submit de mon formulaire.

Mon code

Formulaire de création

import React, {useEffect} from 'react';
import {useForm} from 'react-hook-form';
import {useDispatch, useSelector} from 'react-redux';
import {useHistory} from 'react-router-dom';
import {storePostsActions} from "../../store/actions/posts-actions";

const PostsCreate = () => {

    const {register, handleSubmit} = useForm();
    const dispatch = useDispatch();
    const history = useHistory();
    const posts = useSelector(state => state.posts);

    const submitPost = data => {
        dispatch(storePostsActions(data));
    };

    useEffect(() => {
        if (posts.redirect) {
            history.push(posts.redirect);
        }
    }, [posts]);

    return (
        <div className={'card'}>
            <div className="card-header">
                Création d'un article
            </div>
            <div className="card-body">
                <form onSubmit={handleSubmit(submitPost)}>
                    <div className="form-group">
                        <label htmlFor="title">Titre</label>
                        <input type="text"
                               id={'title'}
                               name={'title'}
                               ref={register}
                               className="form-control"/>
                    </div>
                    <div className="form-group">
                        <label htmlFor="content">Contenu</label>
                        <textarea name="content"
                                  id="content"
                                  cols="30"
                                  rows="10"
                                  ref={register}
                                  className="form-control"/>
                    </div>
                    <button type={'submit'} className="btn btn-primary">Ajouter l'article</button>
                </form>
            </div>
        </div>
    );
};

export default PostsCreate;

Reducer

import {POSTS_ACTIONS_TYPES} from "../actions/actions-types/posts-actions-types";

const initialState = {
    pending: false,
    data: [],
    redirect: false
};

export default (state = initialState, action) => {
    switch (action.type) {
        case POSTS_ACTIONS_TYPES.FETCH.PENDING:
            return {
                ...state,
                pending: action.payload,
                data: null
            };
        case POSTS_ACTIONS_TYPES.FETCH.SUCCESS:
            return {
                ...state,
                pending: false,
                data: action.payload
            };
        case POSTS_ACTIONS_TYPES.STORE.SUCCESS:
            return {
                ...state,
                data: [...state.data, action.payload],
                redirect: '/'
            };
        default:
            return state;
    }
};

Ce que j'obtiens

Je reçois bien ma réponse de succès avec le lien de redirection "redirect", donc je peux rediriger.

Mais la problématique c'est quand je re retourne sur le formulaire, il me redirige directement vers l'accueil car redux à garder en mémoire le state de ma réponse d'avant le "redirect" à "/".

   useEffect(() => {
        if (posts.redirect) {
            history.push(posts.redirect);
        }
    }, [posts]);

Merci d'avance.

3 réponses


Hello Mariolo,

Un peu étrange comme procédé et je ne vois pas bien l'interêt mais why not.
Pour resolver ton probleme t'ajoute un case supplémentaire pour reset ta valeur à false.
Et sur ta page d'accueil tu places un useEffect

          useEffect(() => {
              // le case pour reset ta valeur à false
          },[])

Ca enelvera ta valeur set à '/' dans ton store apres la redirection.

Mais sinon un simplement history.push('/') sans passer par redux fait largement le job.

@+

Mariolo
Auteur

Bonjour,

Merci beaucoup de ta réponse cela m'a aidé. Mais effectivement, je pense m'avoir mal exprimé sur mon objectif final.

Je souhaite faire une création d'un article.

Pour cela j'ai créé un formulaire d'ajout, une fois le formulaire submit je "dispatch" une action.
Cette action elle fait une requête api en post avec axios dans mon API back-end PHP.

Dans mon back-end, je réalise une vérification des champs, etc...

J'aimerais dans mon code React, après le submit et après la réponse renvoyée par axios, je souhaite soit afficher l'erreur s'il y a une erreur, mais si l'article est bien créer je cherche à rediriger vers la liste des articles.

C'est pour cela que j'ai ajouté un champ "redirect" dans mon reducer pour m'avertir que je peux rediriger. Mais je pense que ma méthode n'est pas top. Si tu as une méthode à me proposer ou des conseils je suis preneur car j'essaye de manipuler au mieux react et redux avec de l'api rest.

Merci d'avance.

Hello Mariolo,

Ben dans ton back j'imagine que tu as configurer les choses de maniere à renvoyer un status 200 quand tout est ok et une erreur sur un autre status quand quelque chose ne vas pas.
Si c'est pas le cas je te conseil de le faire. tu renvoies une 403/500 quand ta une erreur avec un message ( "Format du nom invalide").

Et ensuite avec axios tu récup le status

        axios.post(tonApi, {tesData}).then(res =>  {
           if(res.status === 200) {
              history.push('/')
           } else if (res.status === 403/500) {
              Fait autre chose
              recupère le message
           }
        })

        useEffect(() => {
            let mounted = true // Tu peux aussi utiliser les tokens d'axios à la place de ceci 

            if(mounted) {
                    const fetchMesDatas = async () => {
                            dispatch(monactionaestencours(true))
                            try {
                                const mesDatas = await axios.post(tonApi, {tesData})
                                if(mesDatas.status === 200) {
                                      dispatch(monactionaestencours(false))
                                    history.push('/')
                                }
                            } catch(e) {
                                  dispatch(monactionaestencours(false))
                                  throw new Error('balbalbalbalbabl')
                            }
                    }

                    fetchMesDatas()
            }
            return () => {
                    mounted = false
            }
        },[])

ou si tu peux globaliser t'es call

tu créer une instance d'axios ou tu lui passe, l'url de ton api, ton header et derriere tu ajoute un interceptor qui fera le job pour toutes tes requêtes

         // Add a response interceptor
            axios.interceptors.response.use(function (response) {
                  // Any status code that lie within the range of 2xx cause this function to trigger
                  // Do something with response data
                  return response;
            }, function (error) {
                  // Any status codes that falls outside the range of 2xx cause this function to trigger
                  // Do something with response error
                  return Promise.reject(error);
            });
Mariolo
Auteur

Hello

Merci de ta réponse, effectivement je renvoie un statut pour chaque requête de mon API.

Je vais essayer ce que tu m'as donné, merci.

Pour cela j'ai créé un formulaire d'ajout, une fois le formulaire submit je "dispatch" une action.