allen-cell-animated / website-3d-cell-viewer

Other
5 stars 4 forks source link

Use reducers for viewer state #287

Closed frasercl closed 2 months ago

frasercl commented 2 months ago

Review time: small (10-15min)

Problem

Currently, if we try to update multiple viewer or channel settings synchronously, only the last update will be applied:

changeViewerSetting("maskAlpha", 0.5); // overwritten by next update
changeViewerSetting("autorotate", true); // only this update is applied

This is due to the fact that setters like changeViewerSetting produce a new value for viewerSettings by pulling and updating the current value in state. But since that state value only gets updated on every render, multiple synchronous updates will end up pulling and modifying the same stale state value. So e.g. above, the first call produces a new value for viewerSettings by copying the current value and updating maskAlpha, then the second call pulls the same value from before the maskAlpha update and ends up overwriting that pending update!

Solution

useReducer solves this problem. Rather than pulling and updating state ourselves, useReducer lets us define a function which accepts the current state and an action to perform and returns a modified state value. Since the current state value gets passed in from within the bowels of React rather than from the static state value React provides us for a single render, multiple updates can be applied successfully between renders.