Comment obtenir quelque chose de l'état / du magasin dans une fonction redux-saga?

123

Comment accéder à l'état redux dans une fonction saga?

Réponse courte:

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

Réponses:

211

Comme @markerikson le dit déjà, redux-sagaexpose une API très utile select()pour invoquer un selectorétat pour en obtenir une partie disponible dans la saga.

Pour votre exemple, une implémentation 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 doc suggérée par @markerikson, il y a un très bon tutoriel vidéo de D. Abramov qui explique comment l'utiliser selectorsavec Redux. Consultez également ce fil intéressant sur Twitter.

NickGnd
la source
3
Exactement ce que je voulais ... Je ne peux pas croire que je l'ai manqué
Adam Tal
30

C'est à cela que servent les fonctions "sélecteur". Vous leur passez l'arbre d'état entier, et ils renvoient une partie de l'état. Le code qui appelle le sélecteur n'a pas besoin de savoir dans l'état où se trouvaient les données, mais simplement qu'elles ont été renvoyées. Voir http://redux.js.org/docs/recipes/ComputingDerivedData.html pour quelques exemples.

Dans une saga, l' select()API peut être utilisée pour exécuter un sélecteur.

markerikson
la source
Il est intéressant de savoir comment cela a été écrit 3,5 heures avant la réponse acceptée, mais cela n'a pas fourni d'exemple, donc il n'a pas été accepté. Merci de toute façon!
Aleksandar le
1
@Casper - Je suis d'accord! Mais il ne s'agit pas de la rapidité avec laquelle vous répondez à une question, mais de 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.
Adam Tal
@AdamTal oui, je suis d'accord :)
Aleksandar
2

J'ai utilisé un eventChannel pour envoyer une action à partir d'un rappel dans la fonction 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)
    }
}
yardenapp
la source