我有一些钩子可以从api中获取countries数组:
import { useSelector, useDispatch } from 'react-redux'
const useCountries = () => {
const dispatch = useDispatch()
const { countries } = useSelector(data => data)
useEffect(() => {
if (!countries.length) {
dispatch(getCountries())
}
}, [countries])
return {
countries
}
}
我有一些组件不在DOM的同一级别上,并且彼此之间没有关联
const FirstComponent = () => {
const {countries} = useCountries()
// some using of countries array
}
const SecondComponent = () => {
const {countries} = useCountries()
// some using of countries array
}
当页面加载这些组件中的2个时,将执行,并分派2个操作。因为在第一个和第二个组件中还没有选择国家,所以它调用API请求。我的问题是,如果发送了一些请求,我如何才能阻止发送第二个请求。制定一些只发送一次请求的规则,如果尝试发送第二个请求,则阻止它。或者在我的情况下,正确的解决方案或方法是什么?
此外,我也尝试过这样一个案例:
const {
external: { response, isInitial }
} = useSelector(data => data)
useEffect(() => {
if (!response && isInitial) {
dispatch(setIsInitial(false))
fetch()
.then(res => res.json())
.then(data => {
setResponse(data)
})
}
}, [dispatch, response, isInitial])
这是我的减速器:
const initialState = {
response: null,
isInitial: true
}
export default function external(state = initialState, action) {
switch (action.type) {
case types.SET_RESPONSE:
return {
...state,
response: action.payload.data
}
case types.SET_INITIAL:
return {
...state,
isInitial: action.payload.data
}
default:
return state
}
}
但它发送2个请求
您可以如下修改useCountries
:
const useCountries = () => {
const dispatch = useDispatch()
const countries = useSelector(state => state.countries);
const isFetching = useSelector(state => state.isFetching);
useEffect(() => {
if (!countries.length && !isFetching) {
dispatch(getCountries())
}
}, [countries, isFetching])
return {
countries
}
}
您需要翻转getCountries
函数中的isFetching
标志,并在api
解析后再次翻转。
------------------附加信息后编辑------------------
您需要将您的dispatch
呼叫连锁。这是为了确保在进行api调用之前设置了标志。
为了实现这一点,可以通过以下方式使dispatch
成为可能。
dispatch
返回两个选项之一:
对于同步操作(如调度({type:'action'}(,它将返回动作对象(在我的示例中,{type:"action"}(
对于thunk操作(返回函数的操作创建者(,它返回从动作创建者返回相同的结果。
这是第一种情况。
const syncAction = (arg1, arg2) => {
return (dispatch, getState) => {
return Promise.resolve(arg1 + arg2);
}
}
这将是第二种情况。
const asyncAction = (arg1, arg2) => {
return (dispatch, getState) => {
return fetch(/* some request */)
.then(response => dispatch({ type: "RESPONSE_RECEIVED", payload: response }));
};
};
现在有了以上两个,你可以做以下事情:
dispatch(syncAction(...args)).then(() => {
dispatch(asyncAction())
});
在您的情况下为syncAction - isInitial
和asyncAction - getCountries()
。
添加dispatch
以使用可以解决问题的Effect dependencies数组。
const dispatch = useDispatch()
const { countries } = useSelector(data => data)
useEffect(() => {
if (!countries.length) {
dispatch(getCountries())
}
}, [countries, dispatch])