Come ottenere qualcosa dallo stato / negozio all'interno di una funzione redux-saga?


123

Come si accede allo stato redux all'interno di una funzione saga?

Risposta breve:

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

Risposte:


211

Come già dice @markerikson, redux-sagaespone un'API molto utile select()per invocare uno selectorstato sullo stato per averne una parte disponibile all'interno della saga.

Per il tuo esempio una semplice implementazione potrebbe essere:

/*
 * 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});
  }
}

Oltre al documento suggerito da @markerikson, c'è un ottimo video tutorial di D. Abramov che spiega come usarlo selectorscon Redux. Controlla anche questo interessante thread su Twitter.


3
Esattamente quello che volevo .. Non posso credere di averlo perso
Adam Tal

30

A questo servono le funzioni di "selettore". Gli passi l'intero albero dello stato e loro restituiscono un pezzo dello stato. Il codice che chiama il selettore non ha bisogno di sapere dove si trovavano i dati nello stato, ma solo che erano stati restituiti. Vedi http://redux.js.org/docs/recipes/ComputingDerivedData.html per alcuni esempi.

All'interno di una saga, l' select()API può essere utilizzata per eseguire un selettore.


È interessante come questo sia stato scritto 3,5 ore prima della risposta accettata, ma non ha fornito un esempio, quindi non è stato accettato. Grazie comunque!
Aleksandar

1
@Casper - Sono d'accordo! Ma non si tratta di quanto velocemente rispondi a una domanda qui, ma di quanto è buona la tua risposta. Penso che le risposte debbano essere mantenute semplici e di facile lettura. Questa risposta non corrispondeva a quella e la risposta accettata era molto più facile da capire.
Adam Tal

@AdamTal sì, sono d'accordo :)
Aleksandar

2

Ho usato un eventChannel per inviare un'azione da un callback all'interno della funzione del generatore

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)
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.