145 votes

Comment obtenir quelque chose de l'état / du magasin à l'intérieur d'une fonction redux-saga ?

Comment accéder à l'état redux à l'intérieur d'une fonction saga ?

Réponse courte :

import { select } from 'redux-saga/effects';
...
let data = yield select(stateSelectorFunction);

255voto

NickGnd Points 2563

Comme le dit déjà @markerikson, redux-saga expose une API très utile select() pour invoquer un selector sur l'Etat pour avoir mis à disposition une partie de celui-ci dans la saga.

Pour votre exemple, une mise en œuvre simple pourrait être :

/*
 * Selector. The query depends by the state shape
 */
export const getProject = (state) => state.project

// Saga
export function* saveProjectTask() {
  while(true) {
    yield take(SAVE_PROJECT);
    let project = yield select(getProject); // <-- get the project
    yield call(fetch, '/api/project', { body: project, method: 'PUT' });
    yield put({type: SAVE_PROJECT_SUCCESS});
  }
}

En plus de la suggestion doc par @markerikson, il y a un très bon tutoriel vidéo par D. Abramov qui explique comment utiliser selectors avec Redux. Vérifiez également este Un fil intéressant sur Twitter.

3 votes

Exactement ce que je voulais Je ne peux pas croire que je l'ai manqué

36voto

markerikson Points 442

C'est à ça que servent les fonctions "sélecteur". Vous leur passez l'arbre d'état complet, et elles renvoient une partie de l'état. Le code qui appelle le sélecteur n'a pas besoin de connaître dans l'état où étaient les données, juste qu'elles ont été retournées. Voir http://redux.js.org/docs/recipes/ComputingDerivedData.html pour quelques exemples.

Au sein d'une saga, le select() API peut être utilisé pour exécuter un sélecteur.

0 votes

C'est intéressant de voir comment cela a été écrit en 3,5 heures. avant la réponse acceptée, mais elle ne fournissait pas d'exemple, donc elle n'a pas été acceptée. Merci quand même !

1 votes

Casper - Je suis d'accord ! Mais ce qui compte ici, ce n'est pas la rapidité avec laquelle vous répondez à une question, mais la qualité de votre réponse. Je pense que les réponses doivent rester simples et faciles à lire. Cette réponse ne correspondait pas à cela et la réponse acceptée était beaucoup plus facile à comprendre.

0 votes

@AdamTal oui, je suis d'accord :)

3voto

yardenapp Points 21

J'ai utilisé un canal d'événement pour envoyer une action à partir d'une fonction de rappel dans la fonction de générateur.

import {eventChannel} from 'redux-saga';
import {call, take} from 'redux-saga/effects';

function createEventChannel(setEmitter) {
    return eventChannel(emitter => {
        setEmitter(emitter)
        return () => {

        }
      }
    )
}

function* YourSaga(){
    let emitter;
    const internalEvents = yield call(createEventChannel, em => emitter = em)

    const scopedCallback = () => {
        emitter({type, payload})
    }

    while(true){
        const action = yield take(internalEvents)
        yield put(action)
    }
}

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