首页 > 解决方案 > 从另一个存储切片中的一个存储切片调用一个 redux 操作

问题描述

我是redux的新手。在我的应用程序中,我正在使用一些带有 redux thunk 的异步操作。例如,我有这个从 API 加载电影的操作:

export const loadMovies = (url) => async (dispatch) => {
  const response = await fetch(url);
  const result = await response.json();
  const { total_pages: totalPages, results: movies } = result;
  dispatch(moviesLoaded(totalPages, movies));
};

而且我有情况如果没有要加载的电影怎么办(在数据库中搜索没有给我结果)所以我想将状态(它是另一个 redux 存储切片)更新为“没有电影”。并基于该状态呈现不同的组件。

所以我的新动作是这样的:

    export const loadMovies = (url) => async (dispatch) => {
      const response = await fetch(url);
      const result = await response.json();
      if (result) {
      const { total_pages: totalPages, results: movies } = result;
      dispatch(moviesLoaded(totalPages, movies));
      } else {
       dispatch(updateStatus('no-movies')) // updateStatus is imported from another redux store slice
      }
    };

我想知道这样做是否可以。或者,将操作从一个存储切片导入另一个存储切片是一种不好的做法。还有什么是处理这种情况的更好方法。

标签: javascriptreactjsreduxredux-thunk

解决方案


您不需要从另一个商店切片导入操作。您可以在多个存储切片的 reducer 中处理相同的查询电影操作类型。有关详细信息,请参阅允许多个 Reducer 响应相同的操作

例如

import { createStore, applyMiddleware, combineReducers } from 'redux';
import thunk from 'redux-thunk';

const GET_MOVIES_FULFILLED = 'GET_MOVIES_FULFILLED';

function moviesLoaded(totalPages, movies) {
  return {
    type: GET_MOVIES_FULFILLED,
    payload: {
      totalPages,
      movies,
    },
  };
}

export const loadMovies = () => async (dispatch) => {
  //   const response = await fetch(url);
  //   const result = await response.json();
  // mock result
  const result = { total_pages: 0, results: [] };
  const { total_pages: totalPages, results: movies } = result;
  dispatch(moviesLoaded(totalPages, movies));
};

const rootReducer = combineReducers({
  sliceA(state = { totalPages: 0, movies: [] }, action) {
    switch (action.type) {
      case GET_MOVIES_FULFILLED:
        return action.payload;
      default:
        return state;
    }
  },

  sliceB(state = { status: '' }, action) {
    switch (action.type) {
      case GET_MOVIES_FULFILLED:
        if (!action.payload.movies || !action.payload.movies.length) {
          return {
            status: 'no movies',
          };
        }
      default:
        return state;
    }
  },
});

const store = createStore(rootReducer, applyMiddleware(thunk));

store.dispatch(loadMovies() as any).then(() => {
  console.log(store.getState());
});

输出:

{
  sliceA: { totalPages: 0, movies: [] },
  sliceB: { status: 'no movies' }
}

调度GET_MOVIES_FULFILLED动作,在减速器中处理sliceAsliceB

如果没有电影,我们将状态设置sliceB{status: 'no movies'}


推荐阅读