你如何从另一个动作的动作中得到结果?

问题描述

我是 dvajs 的新手。我使用的是 React 17,x、Typescript 4.2.3、antd 4.15.0、umi 3.4.7

问题。 如果我导航到 /s/ 页面代码应该从 API 获取一些类别并向服务器发出另一个请求,此时将它们显示在某些页面上。但是在调用搜索效果的那一刻,类别为空,因此我尝试再次调用 getCategories 操作。但类别仍然是空的。你如何从另一个动作的动作中得到结果?也许有某种调度链?

代码如下

import { fetchCategories,makeSearch } from '@/services/search';
import { CategoriesModelStateSelector,Subscription } from '@@/plugin-dva/connect';
import { Reducer,Effect } from 'umi';
export type SearchModelState = {
  searchResults: Provider[]
  categories: Category[]
}
export type SearchModelType = {
  namespace: string;
  state: SearchModelState;
  effects: {
    getCategories: Effect;
    search: Effect;
  };
  reducers: {
    setCategories: Reducer
    setSearchResults: Reducer
  };
  subscriptions: {
    setup: Subscription
  }
};
export type SearchModelStateSelector = {
  search: SearchModelState
};
const SearchModel: SearchModelType = {
  namespace: 'search',state: {
categories: [],searchResults: [],},effects: {
    * getCategories({ payload },{ call,put,select }) {
      const response = yield call(fetchCategories);
  if (response) {
    yield put({
      type: 'setCategories',payload: response,});
  }
},* search({ payload },select }) {
  let categories = yield select(({ categories: state }: CategoriesModelStateSelector) => state.categories);
  // HERE categories are empty
  console.log(categories);
  yield put({
    type: 'getCategories',payload: {},});

  let catss = yield select(({ categories: state }: CategoriesModelStateSelector) => state.categories);
  console.log(catss);
  // HERE categories are still empty

  const response = yield call(makeSearch,payload);
  yield put({
    type: 'setSearchResults',});
},reducers: {
        setCategories(state,{ payload }) {
          return {
            ...state,categories: response,};
    },setSearchResults(state,{ payload }) {
      return {
        ...state,searchResults: response,subscriptions: {
    setup({ dispatch,history }) {
      // @ts-ignore
      return history.listen(({ pathname,query }) => {
        dispatch({ type: 'getCategories',payload: {} });

        if (pathname === '/s' || pathname === '/s/') {
          dispatch({ type: 'search',payload: query });
        }
      });
    },};

export default SearchModel;

解决方法

建议的解决方案:

Backend - Django + DRF (Rest API)
Frontend - React

Redux-Saga 拍摄: 创建一个 Effect 描述,指示中间件等待 Store 上的指定操作。 Generator 被挂起,直到一个匹配模式的 action 被调度。

https://redux-saga.js.org/docs/api/

我又看了你的代码:

yield put({
    type: 'getCategories',payload: {},});

// something like this will wait until CATEGORIES_WERE_FETCHED was dispatched on 
// the store,before continuing to next line: 'take' is what you are looking for
yield take("CATEGORIES_WERE_FETCHED")

let catss = yield select(

您正在使用 'setCategories' 操作,因此您可以使用 take('setCategories') - 如果您想“等待”某个操作被分派,就像上面的方式一样。