How to get something from the state / store inside a redux-saga function?

74,208

Solution 1

As @markerikson already says, redux-saga exposes a very useful API select() to invoke a selector on the state for getting some part of it available inside the saga.

For your example a simple implementation could be:

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

In addition to the suggested doc by @markerikson, there is a very good video tutorial by D. Abramov which explains how to use selectors with Redux. Check also this interesting thread on Twitter.

Solution 2

This is what "selector" functions are for. You pass them the entire state tree, and they return some piece of the state. The code that calls the selector doesn't need to know where in the state that data was, just that it was returned. See http://redux.js.org/docs/recipes/ComputingDerivedData.html for some examples.

Within a saga, the select() API can be used to execute a selector.

Solution 3

I used an eventChannel to dispatch an action from a callback within the generator function

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)
    }
}
Share:
74,208

Related videos on Youtube

Adam Tal
Author by

Adam Tal

Adam Tal ( אדם טל ) from Israel. Previously known as Adam Fridental ( אדם פרידנטל ). Family man, web developer and C# programmer. Experienced with javascript (react, nodejs, angular, knockoutjs, jquery), ASP.NET (MVC / Web API) and learning new things. Mostly occupied with web development but with great experience with building windows applications. Used to program for fun, These days I program 24/7 for living.

Updated on March 21, 2020

Comments

  • Adam Tal
    Adam Tal about 4 years

    How do I access the redux state inside a saga function?

    Short answer:

    import { select } from 'redux-saga/effects';
    ...
    let data = yield select(stateSelectorFunction);
    
  • Adam Tal
    Adam Tal almost 8 years
    Exactly what I wanted.. I can't belive I missed it
  • Aleksandar
    Aleksandar almost 5 years
    It's interesting how this was written 3.5 hours before the accepted answer, but it didn't provide an example, so it failed to get accepted. Thank You anyways!
  • Adam Tal
    Adam Tal almost 5 years
    @Casper - I agree! But it's not about how fast you answer a question here but how good your answer is. I think answers must be kept simple and easy to read. This answer didn't match that and the accepted answer was much easier to understand.
  • Aleksandar
    Aleksandar almost 5 years
    @AdamTal yes, I agree :)