阻止发送请求两次反应redux(挂钩)



我有一些钩子可以从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 - isInitialasyncAction - getCountries()

添加dispatch以使用可以解决问题的Effect dependencies数组。

const dispatch = useDispatch()
const { countries } = useSelector(data => data)
useEffect(() => {
if (!countries.length) {
dispatch(getCountries())
}
}, [countries, dispatch])

相关内容

  • 没有找到相关文章

最新更新