118 votes

Comment déclencher un callback après la mise à jour de l'état dans Redux ?

En React, l'état n'est pas mis à jour instantanément, nous pouvons donc utiliser un callback dans la fonction setState(state, callback) . Mais comment le faire dans Redux ?

Après avoir appelé le this.props.dispatch(updateState(key, value)) J'ai besoin de faire quelque chose avec l'état mis à jour immédiatement.

Y a-t-il un moyen d'appeler un callback avec le dernier état comme je le fais dans React ?

0 votes

Utilisez-vous thunk ?

2 votes

Je pense dispatch() est une activité synchrone. L'état mis à jour doit être disponible dans la ligne suivante.

4 votes

@PraneshRavi Je le pensais. Mais j'ai obtenu l'ancien état. Je n'ai pas utilisé thunk .

138voto

Kokovin Vladislav Points 5938

doit être mis à jour pour recevoir de nouveaux props.

il existe des moyens d'atteindre votre objectif :

1. composantDidUpdate vérifier si la valeur est modifiée, puis faire quelque chose

 componentDidUpdate(prevProps){
     if(prevProps.value !== this.props.value){ alert(prevProps.value) }
  }

2. redux-promesse ( l'intergiciel distribuera la valeur résolue de la promesse)

export const updateState = (key, value)=>
Promise.resolve({
  type:'UPDATE_STATE',
  key, value
})

puis dans le composant

this.props.dispatch(updateState(key, value)).then(()=>{
   alert(this.props.value)
})

2. redux-thunk

export const updateState = (key, value) => dispatch => {
  dispatch({
    type: 'UPDATE_STATE',
    key,
    value,
  });
  return Promise.resolve();
};

puis dans le composant

this.props.dispatch(updateState(key, value)).then(()=>{
   alert(this.props.value)
})

8 votes

Dans votre redux-thunk par exemple, vous utilisez dispatch comme s'il était synchrone. Est-ce le cas ?

2 votes

@DannyHarding dispatch n'est pas synchrone. Sans le Promise.resolve() , this.props.value renverrait toujours l'ancienne valeur. Une certaine forme de report asynchrone est toujours nécessaire (référencement à partir d'un fichier setTimeout fonctionnerait également par exemple).

4 votes

@DrazenBjelovuk Je me pose la question parce que la fonction updateState dans l'exemple redux-thunk a dispatch(someAction) immédiatement suivi de return Promise.resolve(). La promesse se résout immédiatement, ce qui, j'imagine, créerait une condition de course entre la mise à jour du magasin redux et le .then appelé dans le composant. Comme le dispatch ne renvoie pas de promesse ou n'accepte pas de callback, je ne pense pas que ce soit un moyen précis de savoir quand le redux store a été mis à jour. Je pense que la réponse de just-boris est correcte dans ce cas.

37voto

YairTawil Points 935

Avec l'API Hooks :

useEffect avec l'accessoire en entrée.

import React, { useEffect} from 'react'
import { useSelector } from 'react-redux'

export default function ValueComponent() {
   const value = useSelector(store => store.pathTo.value)

   useEffect(() => {
     console.log('New value', value) 
     return () => {
        console.log('Prev value', value) 
     }

   }, [value])

   return <div> {value} </div>
}

16voto

just-boris Points 5598

Le point le plus important de React est le flux de données unidirectionnel. Dans votre exemple, cela signifie que l'envoi d'une action et la gestion des changements d'état doivent être découplés.

Tu ne devrais pas penser comme "j'ai fait A Maintenant. X devient Y et je m'en occupe ", mais " Que dois-je faire quand X devient Y ", sans aucune relation avec A . L'état du magasin peut être mis à jour à partir de plusieurs sources, en plus de votre composant, Time Travel peut également changer d'état et cela ne sera pas transmis par votre composant. A point d'expédition.

En gros, cela signifie que vous devez utiliser componentWillReceiveProps comme il a été proposé par @Utro

0 votes

C'est la réponse que recherche réellement Op (bien qu'il semble ne pas en être conscient ).

1 votes

Je suis d'accord mais cela semble être considéré comme un anti-modèle : hackernoon.com/

1 votes

Que faisons-nous maintenant que componentWillReceiveProps est déprécié ? static getDerivedStateFromProps() ne semble pas être un remplacement approprié car il ne peut pas appeler un callback, pour autant que je sache

6voto

Pranesh Ravi Points 9005

Vous pourriez utiliser subscribe et il sera appelé lorsqu'une action est distribuée. Dans l'écouteur, vous obtiendrez les dernières données du magasin.

http://redux.js.org/docs/api/Store.html#subscribelistener

2 votes

subscribe ne se déclenche que lorsqu'une action est envoyée. Il n'y a aucun moyen subscribe vous permettra de savoir si votre appel API a retourné des données je pense ! :D

0 votes

Vous pouvez envoyer une autre action lorsque votre demande est terminée (avec ou sans succès).

0 votes

Je ne suis pas convaincu qu'aucune des autres solutions proposées ici ne fonctionne réellement, car je ne vois pas de moyen pour qu'une promesse soit résolue ou qu'un callback se déclenche après la mise à jour de l'état. Cette méthode est appelée pour chaque mise à jour du magasin, pas seulement celle qui se produit après votre événement, mais cela ne devrait pas être trop difficile à contourner. En particulier, le lien écrire un utilitaire observeStore personnalisé de la page dont vous avez donné le lien est très utile.

3voto

acmoune Points 11

Vous pouvez utiliser un thunk avec un callback

myThunk = cb => dispatch =>
  myAsyncOp(...)
    .then(res => dispatch(res))
    .then(() => cb()) // Do whatever you want here.
    .catch(err => handleError(err))

0 votes

Parfait pour ce dont j'avais besoin !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X