redux saga selectors, how do I access state from a saga?

Winter picture Winter · Apr 18, 2017 · Viewed 20.9k times · Source

Similar questions have been asked before, but the answers have not been of any help to me.

What are selectors in redux?

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

I think that I have a different setup since I cannot seem to be able to access state from my saga.

I tried doing:

const getList = store => store;
const getList = state=> state;

these both return undefined.

My store looks like this...

export default function createStoreWithMiddleware() {
    const sagaMiddleware = createSagaMiddleware();
    const loggerMiddleware = createLogger();
    const middleware = [sagaMiddleware, loggerMiddleware];
    const persistedState = localStorage.getItem('reduxState') ? JSON.parse(localStorage.getItem('reduxState')) : {};

    const store = createStore(reducer, persistedState, compose(
        applyMiddleware(...middleware)
    ));

    store.subscribe(() => {
        localStorage.setItem('reduxState', JSON.stringify(store.getState()));
    });

    sagaMiddleware.run(rootSaga);

    return store;
}

And I want to access my list in this saga:

function* selectTender(action) {
    try {
        const response = yield Api.getTenderById(action.payload);
        yield put({type: 'SELECT_TENDER_SUCCEEDED', currentTender: response});
        const list = yield select(getList);
        yield put({type: 'FETCH_CHAPTERS', chaptersList: list, tenderId: response.id});
    } catch (err) {
        yield put({type: 'SELECT_TENDER_FAILED', message: err.message});
    }
}

export function* watchSelectTender(){
    yield takeEvery('SELECT_TENDER', selectTender);
}

But like I said, both state and store are undefined.

So, how do I access my store (or state) in the saga?

Answer

Vishal Sharma picture Vishal Sharma · Apr 18, 2017

You will have to use selectors for that. I'll give a simple example. Create a file selectors.js and add the fields you want to select from your store, as shown below.

export const username = (state) => state.user.name;

Then in your saga, import the selectors as,

import * as selectors from './selectors';

and when you require username in your saga, you can simply do,

import {select} from 'redux-saga/effects';
...
...
function *sampleSaga(params) {
   const username = yield select(selectors.username);
}

the constant username in sampleSaga will now hold the username value from state.