在 redux 传奇中的 getState?

我有一家商店,上面有商品清单。当我的应用程序第一次加载时,我需要反序列化这些项,比如根据这些项创建一些内存中的对象。这些项目存储在我的 redux 存储和处理的 itemsReducer

我正在尝试使用 还原传奇来处理反序列化,作为一个副作用。在第一页加载时,我发送一个操作:

dispatch( deserializeItems() );

我的故事很简单:

function* deserialize( action ) {
// How to getState here??
yield put({ type: 'DESERISLIZE_COMPLETE' });
}


function* mySaga() {
yield* takeEvery( 'DESERIALIZE', deserialize );
}

在我的反序列化传奇中,我希望处理创建项目的内存中版本的副作用,我需要从存储中读取现有数据。我不知道在这里该怎么做,或者这是不是我应该尝试的模式。

68055 次浏览

you can use select effect

import {select, ...} from 'redux-saga/effects'


function* deserialize( action ) {
const state = yield select();
....
yield put({ type: 'DESERIALIZE_COMPLETE' });
}

also you can use it with selectors

const getItems = state => state.items;


function* deserialize( action ) {
const items = yield select(getItems);
....
yield put({ type: 'DESERIALIZE_COMPLETE' });
}

Select effect does not help us if we in a callback functions, when code flow is not handled by Saga. In this case just pass dispatch and getState to root saga:

store.runSaga(rootSaga, store.dispatch, store.getState)

And the pass parameters to child sagas

export default function* root(dispatch, getState) { yield all([ fork(loginFlow, dispatch, getState), ]) }

And then in watch methods

export default function* watchSomething(dispatch, getState) ...

In addition to the answer from @Kokovin Vladislav, if we like to use typing of Typescript, we could use "defined typed hooks" pattern introduced by redux-toolkit on this doc: https://redux-toolkit.js.org/tutorials/typescript#define-typed-hooks.

So, in the app/hooks.ts file we have:

import { useDispatch, useSelector } from 'react-redux'
import type { TypedUseSelectorHook } from 'react-redux'
import type { RootState, AppDispatch } from './store'


import { select } from 'redux-saga/effects'


// Use throughout your app instead of plain `useDispatch` and `useSelector` ( From redux-toolkit docs )
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector


// THIS IS THE ADDITIONAL SELECTOR!!!!!!!
export function* appSelect<TSelected>( selector: (state: RootState) => TSelected, ): Generator<any, TSelected, TSelected> { return yield select(selector); }

Then in your generator function, you could do similar like this:

import { appSelect } from "app/hooks"


function* deserialize( action ) {
const items = yield* appSelect(state => state.items);
....
yield put({ type: 'DESERIALIZE_COMPLETE' });
}

That way we have strong typing and intelisense of state on each call of appSelect().

Credit: https://github.com/redux-saga/redux-saga/issues/970#issuecomment-880799390