Redux saga 和 redux 工具包

问题描述 投票:0回答:6

我一直在尝试将 redux sagas 和 redux 工具包引入到我的项目中。我目前遇到的问题是观察者传奇没有捕捉到

takeEvery
效果中调度的操作并运行处理程序。我看不出代码有什么问题。谁能帮忙!!!

import { configureStore, getDefaultMiddleware  } from '@reduxjs/toolkit'
import createSagaMiddleware from 'redux-saga'
import logger from 'redux-logger';

import createReducer from './rootReducer';
import sagas from './rootSaga';


const configureAdminStore = (initialState = {}) => {
    const sagaMiddleware = createSagaMiddleware();
  
    // sagaMiddleware: Makes redux-sagas work
    const middlewares = [sagaMiddleware, logger];

  
    const store = configureStore({
      reducer: createReducer(),
      middleware: [...getDefaultMiddleware({thunk: false}), ...middlewares],
      preloadedState: initialState,
      devTools: process.env.NODE_ENV !== 'production',
    });
    
    sagaMiddleware.run(sagas);
  
    return store;
  }

  export default configureAdminStore;

import {put, take, takeEvery, call} from 'redux-saga/effects'
import {getAll} from './environmentSlice'
import {confApi} from '../../service/conf-api'
import { getData } from '../../lib/conf-api-response';


function* getAllEnvironments() {
    const response = yield call(confApi.admin.getEnvironments());
    const {environments} = yield call(getData(response));
    yield put(getAll(environments));
}

// eslint-disable-next-line import/prefer-default-export
export function* watchGetAllEnvironments() {
     yield takeEvery(getAll().type, getAllEnvironments);
}

import { createSlice } from '@reduxjs/toolkit'

const environmentSlice = createSlice({
    name: 'environments',
    initialState: [],
    reducers: {
        getAll: (state, action) => {
            state = action.payload
        },
    },
  })

  export const {getAll} = environmentSlice.actions

  export const { getAllSuccess } = environmentSlice.actions;
  
  export default environmentSlice.reducer

  export const environmentSelector = (state) => state.environments

import {all} from 'redux-saga/effects'
import {watchGetAllEnvironments} from './environments/environmentSaga'

export default function* rootSaga() {
    yield all([
        watchGetAllEnvironments(),
    ])
  }

redux-saga redux-toolkit
6个回答
9
投票

如果您有兴趣创建可以解析/拒绝异步 thunk 操作的 sagas,请查看我创建并使用的 saga-toolkit 包。

slice.js

import { createSlice } from '@reduxjs/toolkit'
import { createSagaAction  } from 'saga-toolkit'

const name = 'example'

const initialState = {
  result: null,
  loading: false,
  error: null,
}

export const fetchThings = createSagaAction(`${name}/fetchThings`)
export const doSomeMoreAsyncStuff = createSagaAction(`${name}/doSomeMoreAsyncStuff`)

const slice = createSlice({
  name,
  initialState,
  extraReducers: {
    [fetchThings.pending]: () => ({
      loading: true,
    }),
    [fetchThings.fulfilled]: ({ payload }) => ({
      result: payload,
      loading: false,
    }),
    [fetchThings.rejected]: ({ error }) => ({
      error,
      loading: false,
    }),
  },
})

export default slice.reducer

sagas.js

import { call } from 'redux-saga/effects'
import { takeLatestAsync, takeEveryAsync, putAsync } from 'saga-toolkit'
import API from 'hyper-super-api'
import * as actions from './slice'

function* fetchThings() {
  const result = yield call(() => API.get('/things'))

  const anotherResult = yield putAsync(actions.doSomeMoreAsyncStuff()) // waits for doSomeMoreAsyncStuff to finish !

  return result
}

function* doSomeMoreAsyncStuff() {
  ...
  return 'a value for another result'
}

export default [
  takeLatestAsync(actions.fetchThings.pending, fetchThings), // takeLatestAsync: behaves a bit like debounce
  takeEveryAsync(actions.doSomeMoreAsyncStuff.pending, doSomeMoreAsyncStuff), // each action will start a new saga thread
]

2
投票

看起来您只服用

getAll().type
两次 - 一次在
watchGetAllEnvironments
,一次在
getAllEnvironments

这意味着

watchGetAllEnvironments
将执行
getAllEnvironments
,但这会立即暂停并等待另一个
getAll
操作被调度,这可能永远不会发生。

所以你可能想先删除

take
中的
getAllEnvironments

另外,你可以

take(getAll)
,没有必要
take(getAll().type)


0
投票

官方文档可能会有所帮助,

import { applyMiddleware, createStore } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import thunkMiddleware from 'redux-thunk'

import monitorReducersEnhancer from './enhancers/monitorReducers'
import loggerMiddleware from './middleware/logger'
import rootReducer from './reducers'

export default function configureStore(preloadedState) {
  const middlewares = [loggerMiddleware, thunkMiddleware]
  const middlewareEnhancer = applyMiddleware(...middlewares)

  const enhancers = [middlewareEnhancer, monitorReducersEnhancer]
  const composedEnhancers = composeWithDevTools(...enhancers)

  const store = createStore(rootReducer, preloadedState, composedEnhancers)

  if (process.env.NODE_ENV !== 'production' && module.hot) {
    module.hot.accept('./reducers', () => store.replaceReducer(rootReducer))
  }

  return store
}

来源:官方示例


0
投票

如果这对新人有帮助的话,我发现 redux-toolkit 很酷,但仍然有点复杂,特别是当你加入 sagas 时(这本质上是异步魔法和神秘)。我最终制作了类似的东西,我称之为“saga slice”。它是 redux 工具包的衍生品,但从一开始就添加了 sagas。你基本上有你的reducers,它操纵状态,你的sagas,它进行异步调用并调度其他状态。为了简化您设置的示例,它最终看起来像这样: import { put } from "redux-saga/effects"; import { createModule } from 'saga-slice'; const environmentSlice = createModule({ name: 'environments', initialState: [], reducers: { getAll: () => {}, getAllSuccess: (state, payload) => { state.splice(0, state.length); payload.forEach(data => state.push(data)); }, }, sagas: (A) => ({ *[A.getAll]({ payload }) { const response = yield call(confApi.admin.getEnvironments()); const { environments } = yield call(getData(response)); yield put(A.getAllSuccess(environments)); } }) });

这基本上会做你想做的同样的事情,而不需要令人困惑的 
watchGetAllEnvironments

rootSaga
的东西(我觉得这很令人费解)。 Saga 切片可配置为使用
takeEvery
takeOne
或您想要使用的任何其他效果,无需太多麻烦。它是配置对象,而不是
yield takeEvery()
。我还提供了帮助程序,通过包含与 saga 的任务取消相关的
axios
包装器来促进您正在做的一些事情,简化请求生命周期,并基于标准 REST 原则构建默认 CRUD 模块。查看文档以获得更全面的解释,并随时提出问题!
    


0
投票
https://redux-toolkit.js.org/api/createAction

中描述。


0
投票
https://www.reddit.com/r/react/comments/1b8cn6u/is_redux_still_a_thing/

© www.soinside.com 2019 - 2024. All rights reserved.