dvajs / dva

🌱 React and redux based, lightweight and elm-style framework. (Inspired by elm and choo)
https://dvajs.com/
MIT License
16.24k stars 3.17k forks source link

[Question] How to get results of an action in another action? #2429

Closed bldgk closed 3 years ago

bldgk commented 3 years ago

Hello! I am newbee in the dvajs. I am using React 17,x, Typescript 4.2.3, antd 4.15.0, umi 3.4.7. If this question is inappropriate in this repo, I'll ask in the umi.

If I navigate to a page /s/, the code has to get some categories from API and perform another request to the server while displaying it on some pages. But at the moment, when search effect is called, categories are empty, so I trying to call action getCategories again. But the categories are still empty. How to get results from another action? Maybe there is some dispatch chain?

The code is provided below and in attached search2.txt

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 }, { call, put, 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',
    payload: response,
  });
},
},

    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;