Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 阻止发送请求两次react redux(挂钩)_Reactjs_React Redux_React Hooks - Fatal编程技术网

Reactjs 阻止发送请求两次react redux(挂钩)

Reactjs 阻止发送请求两次react redux(挂钩),reactjs,react-redux,react-hooks,Reactjs,React Redux,React Hooks,我有一些从api获取countries数组的钩子: import { useSelector, useDispatch } from 'react-redux' const useCountries = () => { const dispatch = useDispatch() const { countries } = useSelector(data => data) useEffect(() => { if (!countries.length) {

我有一些从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个请求

您可以修改您的
使用国
,如下所示:

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
解析后再次翻转它

------------------附加信息后编辑-----------------------

您需要将
分派
呼叫链接起来。这是为了确保在进行api调用之前设置该标志

要实现这一点,您可以通过以下方式使
分派
表格

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()

添加
调度
,以使用Effect dependencies数组来解决问题

 const dispatch = useDispatch()

 const { countries } = useSelector(data => data)

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

你可以有一个
fetching
标志。另外,你可以编写逻辑,这样只有当state没有值或者你需要刷新state并且fetching不是true时才会调用api。你能附上一些代码解决示例吗,请针对我的情况!发布了一个答案。你的意思是分派一些将isFetching设置为true的操作吗?它将l不起作用,因为这些钩子几乎会同时被调用,您能展示一下如何在reducer中设置isFetching吗?
dispatch
在本质上总是同步的。您可以有一个专门设置标志的
dispatch
。您可以在进行api调用之前
dispatch
。这样,只有一个
dispatch。另一个将通过useEffect进行干运行,因为它不会进入
if
块。您可以将减速机添加到帖子中。我将编辑它。您需要链接
调度
调用,我将在我的答案中添加示例。导出函数setIsInitial(){return(dispatch,getState)=>{const{external}=getState()如果(external.isInitial){return Promise.resolve(dispatch({type:types.SET_是_INITIAL_SUCCESS,payload:{data:false}}))}返回Promise.reject()}谢谢,你帮了我很多忙