Jak zdobyć coś od państwa / sklepu w ramach funkcji sagi redux?

123

Jak uzyskać dostęp do stanu redux w funkcji sagi?

Krótka odpowiedź:

import { select } from 'redux-saga/effects';
...
let data = yield select(stateSelectorFunction);
Adam Tal
źródło

Odpowiedzi:

211

Jak już mówi @markerikson, redux-sagaujawnia bardzo przydatne API, select()które wywołuje selectorstan w celu uzyskania jego części dostępnej w sadze.

Na przykład prostą implementacją może być:

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

Oprócz sugerowanego dokumentu autorstwa @markerikson, istnieje bardzo dobry samouczek wideo autorstwa D. Abramova, który wyjaśnia, jak korzystać selectorsz Redux. Sprawdź też ten ciekawy wątek na Twitterze.

NickGnd
źródło
3
Dokładnie to, czego chciałem… Nie mogę uwierzyć, że to przegapiłem
Adam Tal
30

Do tego służą funkcje „selektora”. Przekazujesz im całe drzewo stanu, a oni zwracają część stanu. Kod, który wywołuje selektor nie musi wiedzieć, gdzie w państwie, które dane było tylko, że został zwrócony. Zobacz http://redux.js.org/docs/recipes/ComputingDerivedData.html po kilka przykładów.

W sadze select()API może służyć do wykonywania selektora.

markerikson
źródło
Ciekawe, jak to zostało napisane 3,5 godziny przed zaakceptowaną odpowiedzią, ale nie zawierało przykładu, więc nie zostało zaakceptowane. W każdym razie dziękuję!
Aleksandar
1
@Casper - zgadzam się! Ale nie chodzi o to, jak szybko odpowiadasz tutaj na pytanie, ale o to, jak dobra jest twoja odpowiedź. Myślę, że odpowiedzi muszą być proste i łatwe do odczytania. Ta odpowiedź nie pasowała do tego, a zaakceptowana odpowiedź była znacznie łatwiejsza do zrozumienia.
Adam Tal,
@AdamTal tak, zgadzam się :)
Aleksandar
2

Użyłem eventChannel do wywołania akcji z wywołania zwrotnego w funkcji generatora

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
źródło