react函数组件中可以根据usestate的顺序确定赋值成功的顺序吗?

const [a, seta] = useState({})
const [b, setb] = useState(false)

Promise.resolve().then(() => {
    seta({name:'xxxxx'})
    setb(true)
})

useEffect(() => {
    if (b) {
      // do something
      // 这里a是否一定被成功赋值
    }
}, [b])

上面的代码我是想等 a赋值完成后做一些操作(代码中的do something),但是由于代码中seta的地方比较多,所以就没法在useEffect去监听a的变化。

所以我在seta后面加了一个setb,然后在useEffect中监听如果btrue的时候去做操作。

请问下代码中 do something这里此时a一定被赋值成功了吗?我现在在代码中这么写是能正常运行的,但是不知道会不会有什么bug或者不严谨的地方,请大佬们指教下

react react-dom版本16.13.1

阅读 2.5k
2 个回答

首先,在 react 中不要直接在 函数组件 中直接调用 setState, 这就是一个错误用例。setState 会导致函数组件重新执行,这样写其实就是写了一个死循环

const [a, seta] = useState({})
const [b, setb] = useState(false)

Promise.resolve().then(() => {
    seta({name:'xxxxx'})
    setb(true)
})

如果你的这段逻辑是一些初始化操作,那么应该放到 useEffect 中

const [a, seta] = useState({})
const [b, setb] = useState(false)

useEffect(() => {
  Promise.resolve().then(() => {
      seta({name:'xxxxx'})
      setb(true)
  })
}, [])

下面再回到你的问题,通过正常的事件流去执行 setA,setB 是否有顺序问题,取决于你是在异步任务中去 setState,还是在同步任务中。

  1. 首先说异步,异步中 setState 在 react18 之前不会被合并执行,所以需要保证 setA,setB 的调用顺序才能保证最后的执行正常
  2. 同步的话则不存在顺序问题,setA,setB 的顺序可以任意放置,最终 react 会合并更新完所有状态,执行一次组件更新

React hooks 是按顺序执行的。鉴于你的场景什么赋值成功的不太清楚,只能提供些建议:

  1. useState(fn) 提供一个函数进行初始化 state
  2. useEffect 里判断你想要赋值成功之前的 value
  3. 或者写个 once 一次性函数判断

顺便提一句,React 18 开始默认启用 concurrent mode,setState 如果数据量比较大会被分片更新(异步的),一般情况下近似于同步。比如你的例子中就能进行这样的判断

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题