您如何从另一个动作中获得动作的结果?
How do you get the result from action in another action?
我是 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 }, { 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;
建议的解决方案:
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(
Redux-Saga 采取:
创建一个 Effect 描述,指示中间件等待 Store 上的指定操作。 Generator 被挂起,直到匹配模式的动作被调度。
https://redux-saga.js.org/docs/api/
我又看了一遍你的代码:
yield put({
type: 'setCategories',
payload: response,
});
您正在使用 'setCategories' 操作,因此您可以使用 take('setCategories') - 如果您想 'wait' 直到某个操作被调度,就在上面的方式中。
我是 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 }, { 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;
建议的解决方案:
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(
Redux-Saga 采取: 创建一个 Effect 描述,指示中间件等待 Store 上的指定操作。 Generator 被挂起,直到匹配模式的动作被调度。
https://redux-saga.js.org/docs/api/
我又看了一遍你的代码:
yield put({
type: 'setCategories',
payload: response,
});
您正在使用 'setCategories' 操作,因此您可以使用 take('setCategories') - 如果您想 'wait' 直到某个操作被调度,就在上面的方式中。