比如下面的代码,用一个简单 submitting 来说明(不是实际的业务需求,只是个演示)。

如果真的要在回调里去读取当前的 submitting 状态,有什么方法吗?

我知道有一个 useEffect hook ,去监听 submitting 状态的变更。但是感觉这样好麻烦,实际业务中,状态一多,就是一团麻的感觉。另外,有时候状态变更并不能很精准的表达实际发生的事情。就拿这个 submitting 来说。它可能是用户点击了 button 触发的,也可能是通过其它事件方式触发的,如果这些触发的事件也是业务需要考虑的,那简单的监听 submitting 变更似乎不能满足业务需求(可能还要加个类似 trigger by 的状态?)。


```jsx
import { useState } from "react";


export const DebugPage = () => {
  const [submitting, setSubmitting] = useState(false);

  const handleSubmit = () => {
    setSubmitting(true);

    // 用 setTimeout 模拟异步请求
    setTimeout(() => {
      // 在异步回调的时候,这个 submitting 的状态依然是 false 。
      // 这个我能理解。因为这个生成这个词法闭包上的时候 submitting 就是 false 。
      //
      // 但是假如我需要在这里读取 submitting 当前的准确状态,要怎么做?有办法做到吗?
      console.log('submitting: ', submitting);
      setSubmitting(false);
    }, 1000);
  }

  return (
    <button onClick={handleSubmit}>{submitting ? 'Submitting' : 'Submit'}</button>
  )
}
```

不知道有没有描述清楚我的问题。谢谢各位~
举报· 311 次点击
登录 注册 站外分享
10 条回复  
sukinee 小成 2024-5-10 17:27:10
useRef
Leviathann 初学 2024-5-10 17:33:32
用 ref 记录 submitting ,每次 setState 的时候都同步修改 ref

相当于 setState 只用作触发 rerender
lisongeee 小成 2024-5-10 17:43:39
```js
const [submitting, setSubmitting] = useState(false);

const onClick = async () => {
    setSubmitting(true);
    const r = await fetch('/api/hello').then((r) => r.json());
    const latestValue = await new Promise<boolean>((res) => {
        setSubmitting((v) => (res(v), v));
    });
    console.log(latestValue)
};
```
weixind 小成 2024-5-10 17:49:14
当你想多处触发同一个 submitting 的时候思路已经有点偏了。state 状态要分离,应该有个 handleSubmitting 。或者直接用 useQuery 之类的东西。你提交的 loading 就是提交的 loading 。其他的 loading 和他样式可以一样,但是逻辑不要揉到一块。如果你觉得 state 多了会是一团乱麻。多处逻辑更改同一个 state 才更是一团乱麻。追踪变更都追踪不到。
Puteulanus 初学 2024-5-10 17:59:40
有个邪教方法能取到
setSubmitting 接受一个函数作为输入,你可以传一个 a => a+1 给它,在不知道 Submitting 值的情况下来给 Submitting 加一,换句话说这个函数肯定是能拿到你想要的“当前”值的,只是函数不一定同步执行
所以有
https://i.imgur.com/JmiJ6MG.png

当然这种主要是写着好玩,常规做法你还是看看楼上的,这种代码写多了容易被 review 的掐死。。
codehz 初学 2024-5-10 19:21:57
我建议用一下 swr 这类请求封装好的吧,你这样滥用 swr 迟早会出事()
另外正统的读 state 当前值的方法是传递一个函数给 setState(current => { /* play with current */ return current; })
yukinotech 小成 2024-5-10 20:19:00
@codehz setState(current => { /* play with current */ return current; })  太艹了
northquq 初学 2024-5-11 09:53:30
https://ahooks.js.org/hooks/use-latest/
看看这个?
sh666 小成 2024-5-11 10:14:51
setSubmitting((prev) => {
        console.log('submitting: ', prev);
        return prev;
      });
      setSubmitting(false);
12下一页
返回顶部