简体   繁体   English

关于在 React 上使用钩子排队状态更改的问题

[英]Question about queueing state changes with hooks on React

So, I've started studying React by doing class components.所以,我开始通过做类组件来学习 React。 There, as far as I understood what I was doing, if I had a在那里,据我所知,我在做什么,如果我有一个

this.state = {
  isLoading: false,
  dataToRender: [],
}

this.setState({ isLoading: true }, async () => {
 const data = await fetchData();
 this.setState({ dataToRender: data , isLoading: false });
})

const message => <p>loading...</p>

if (isLoading) return message();

return (
 dataToRender.map
)

for displaying a "loading" message whenever I call an API for new data, I could know that the setState "queue" would be executed in an order.为了在我为新数据调用 API 时显示“正在加载”消息,我可以知道 setState“队列”将按顺序执行。 The outer setState would receive a first state change on the first parameter and a function to execute right after it as the second parameter.外部 setState 将接收第一个参数的第一个状态更改和一个在其后作为第二个参数立即执行的函数。

The problem is that I'm having a bit of difficulty wrapping my head around ways to achieve this with hooks.问题是我在用钩子实现这一点的方法上有点困难。 I'm assuming doing我假设做

const [isLoading, setIsLoading] = useState(false);
const [data, setData] = useState([]);

setLoading(async () => {
  setLoading(true)
  const data = await fetchData()
  setData(data);
  return false;
})

wouldn't work, right?行不通,对吧? I feel like the overall logic of building this kind of component logic may be different when using hooks somehow... If anyone could at least point me to concept direction it would be nice.我觉得以某种方式使用钩子时,构建这种组件逻辑的整体逻辑可能会有所不同……如果有人至少能指出我的概念方向,那就太好了。 Thanks!谢谢! :) :)

There's no callback with the dispatch function of useState . useState的 dispatch 函数没有回调。

  const fn = async () => {
    setIsLoading(true)
    const data = await fetchData()
    setData(data)
    setIsLoading(false)
  })

The above function is normally invoked upon an event such as onClick or useEffect .上述函数通常在onClickuseEffect等事件上调用。

The functions passed as a useState state update function are treated as synchronous functions, so you are effectively saving the implicitly returned Promise object into state.作为useState状态更新函数传递的函数被视为同步函数,因此您可以有效地将隐式返回的 Promise 对象保存到状态中。

What you should do is factor the asynchronous logic into a function that is called from an event handler, like onClick , or is called in a component lifecycle, like useEffect .您应该做的是将异步逻辑分解为从事件处理程序调用的函数(如onClick )或在组件生命周期中调用的函数(如useEffect

const [isLoading, setIsLoading] = useState(false);
const [data, setData] = useState([]);

const asyncCall = async () => {
  setLoading(true);
  try {
    const data = await fetchData();
    setData(data);
  } catch(error) {
    // handle any errors, logging, etc...
  } finally {
    setLoading(false);
  }
};

This will call/enqueue each state update in the order they are enqueued.这将按照入队的顺序调用/入队每个状态更新。 You should also surround any asynchronous logic in a try/catch block so you can handle any rejected promises, clear the loading state in a finally so that regardless of resolved/rejected promises, when the code completes it resets the loading state.您还应该在try/catch块中包含任何异步逻辑,以便您可以处理任何被拒绝的承诺,在finally清除加载状态,以便无论已解决/拒绝的承诺如何,当代码完成时,它都会重置加载状态。

depending on Kent React normally batches these calls so you only get a single re-render, but it's unable to do this in an asynchronous callback (like our promise success and error handlers).取决于 Kent React 通常对这些调用进行批处理,因此您只能获得一次重新渲染,但它无法在异步回调中执行此操作(例如我们的 promise 成功和错误处理程序)。 You can use object for value of useState or use useReducer.您可以使用对象作为 useState 的值或使用 useReducer。

const [state,setState]=useState({isLoading:false,success:false,isError:false,data:[]})

then setting those property on each status.然后在每个状态上设置这些属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM