React:合并与分离状态,以及设置程序/调度程序的顺序



设置

我正在React中通过自定义钩子创建一个游戏。它有许多状态需要跟踪,还有许多常数是根据这些状态计算出来的。

例如,董事会有州,所有行动的历史,以及谁(如果有人(被没收,等等。游戏状态(正在进行、获胜等(、谁(如果有人(获胜、轮到谁等等都是常量。

"相关的";州

特别是,董事会和搬家历史紧密相连,应该一起更新。(事实上,董事会可以根据搬迁历史来计算。但假设我不想这样做,我更愿意将董事会作为一个州。(

每当有人搬家时,我都需要更新这两个。如果它们是独立的状态,那么我需要使用两个setter/dispatcher的序列这里的潜在问题是,如果React在这两者之间重新渲染,则状态将不同步,并且一些副作用(通过useEffects(将出现故障。我知道React捆绑了状态更新,但在使用异步代码时似乎无法保证这一点(例如,setTimeout模拟计算机玩家的思维——这导致了这个问题发生在我身上(。

因此,在这样的情况下,将两者捆绑成一个状态对象似乎是最合乎逻辑的。(如果我错了,请纠正我。(

"独立的";州

另一方面,董事会和是否有人被没收是独立的。您通常不会期望这两个状态同时更新。(这类配对还有其他例子。(

在这种情况下,将它们作为单独的状态似乎是最合乎逻辑的。将它们捆绑在一起是可能的(连同上面的移动历史(,但直觉上感觉有点错误。

问题

到目前为止,按照上述合并相关国家和保持独立国家分离的策略,一切似乎都很好。

不过,当我重置游戏时呢?如上所述,虽然棋盘和谁被没收是独立的,但事实上,我确实想在重置游戏时同时更改它们(以及大多数其他状态(。如果这些状态中有许多是独立的,那么我必须(据我所知(使用一系列setter/dispatcher来依次更新每个状态。(它们不能通过副作用发生,因为在副作用发生之前它们会"不同步",而且由于它们的性质,它们不能是无状态的,也不能从其他状态计算。(

我们回到,在这个序列的中间可能有一个re-render的问题。(同样,这种情况似乎很少见,但在使用异步代码时似乎确实会发生。(

根据我上面的推理,解决方案似乎是将所有需要重置的状态合并为一个状态。得出的结论是,对于我所做的大多数挂钩,大多数/所有状态都应该捆绑到一个状态中。但总是这样做似乎很奇怪——概念上不同的概念似乎应该处于不同的状态。

(可以尝试以这样一种方式对setter/dispatch调用进行排序,即在中间不会发生任何不好的事情,但这可能并不总是可能的,即使是这样,这似乎也是解决问题的糟糕方法。(

问题

我的推理有错吗?我真的需要把我的所有状态合并到一个状态中,这样重置游戏就可以了吗?或者有其他方法可以解决单独状态"不同步"的问题吗?

(在这种特殊情况下,可以通过卸载和重新安装调用钩子的组件来实现重置,但在其他情况下,如果在重置期间需要保留某些状态,或者如果操作不是重置,则可能无法实现。(

一个类似的问题React挂钩:为什么异步函数中的多个useState setter会导致多个重发?有最终解决这个问题的答案。

不需要,不需要将所有状态合并为一个状态来确保重置顺利进行您可以使用unstable_batchedUpdates来防止React在setter之间重新报价(有关详细信息和示例,请参阅上面链接的问题(。

事实上,在React 18中,unstable_batchedUpdates甚至是不必要的——React将自动处理来自异步调用(如setTimeout等(的事件的批处理,就像它目前处理React事件的方式一样。有关详细信息和示例,请参阅本次GitHub讨论。

相关内容

最新更新