如何使用React Hooks触发调用以调度?

时间:2020-06-01 17:31:03

标签: reactjs redux react-redux

我在一个组件中有一个save函数,该函数对API进行一些调用并根据响应更改我的本地状态。然后,我想调度一次操作,并且仅一次完成对setState的调用,例如

const [myData, setMyData] = useState([{id: 0, name: "Alex"}]);

const save = async () => {

    if (someCondition) {
        let response = await axios.get("/someroute");
        if (response.status === 200) {
            setMyData([...myData, response.data])])
        }
    }

    if (someOtherCondition) {
        let response2 = await axios.get("/someotherroute");
        if (response2.status === 200) {
            setMyData([...myData, response2.data])])
        }
    }

    dispatch(myAction(myData));
}

现在我知道useEffect应该是解决此问题的方法。例如

useEffect(() => {
    dispatch(myAction(myData));
}, [myData]);

但是我要在组件中的其他位置更改myData,并且我只想在调用save()并且完成setMyData后才调度操作。我想不出要检查useEffect()的条件,除了可能在myData中添加某种标志,就像一个对象说“准备保存”,但感觉应该更简单一些。方式。

非常感谢您对此提供的任何帮助!

2 个答案:

答案 0 :(得分:1)

在其他地方更改myData是什么意思?您是否正在通过从某处获取myData来更改它?因为如果不这样做,setMyData将会非常简单快速地完成其工作。因此,您的保存功能无需监听。

如果由于其他某些获取和保存功能而更改了myData,则应等待它。然后故事会有点复杂。您可能想检查中间件和redux sagas。

我很难理解您的情况和用例;但是,如果在连续的提取操作期间您担心状态覆盖,那么传奇中间件可以解决这个问题。

例如,您可以使用takeLatest创建一些传奇的中间件,以便它将采取已调度的最后一个操作并杀死正在进行的上一个(不等待)操作;因此您可以避免由于副作用而导致的数据覆盖。或者类似地,您可能想要使用takeEvery,它将对设置myData的每个操作进行排队,并且它们将彼此等待结束。

检查更多:https://redux-saga.js.org/

和用法示例:https://codesandbox.io/s/385lk3x6v1?file=/src/sagas/index.js

答案 1 :(得分:0)

似乎您需要使用useReduce来代替,然后您就可以检测到useEffect中任何道具何时发生了变化:


const initialState = {
  id: null,
  name: null,
  ...
}
const [state, dispatch] = useReducer((state, action) => {
  switch (action.type) {
    case 'CHANGE-NAME':
      return { ...state, name: action.value }
    default:
      throw new Error('Type not defined')
  }
}, initialState)

useEffect(() => {
  // Notify changes!!
}, [state.name]);


...
const myFun = async () {
  // do something
  dispatch({ type: 'CHANGE-NAME', value: 'Hello world' })
}

此外,您还可以将其他道具添加到初始状态,例如,如果您需要特定的标志来一次检测动作,则:)

致谢