Skip to content

Latest commit

 

History

History
9 lines (6 loc) · 2.29 KB

File metadata and controls

9 lines (6 loc) · 2.29 KB

components

Ink-based React components that can be reused by screens.

Timer

The timer warrants a deeper discussion. Its useEffect callback actually plays an integral role for the in-game screen. Not only does the timer display the remaining time in the round that is stored in gamestate, but it also sends TICK actions to the state. The TICK actions are hooked up to a one-second timer by registering a callback with the setInterval JavaScript API. That API also provides a mechanism for deregistering the callback (clearInterval), so that the ticking can stop when the timer is removed from the screen.

Handling callback registration and deregistration is what useEffect is really for in React (see: Synchronizing with Effects), even though you will probably most commonly encounter useEffect being used for fetching data to update a component's state. React 18 strict mode will introduce surprising behavior for developers who are used to that pattern, and the docs have been updated explaining how to use useEffect for fetching without running into the problems that are inherent to following this pattern.

There's an interesting consequence of registering the timer here in the React component: nothing in gamestate knows that ticks are 1 second. This component can choose to tick faster or slower, by simply changing the constant passed into setInterval, and the game logic will respond the same irrespective of the "wall clock time" that has actually passed. That means unit tests for the gamestate do not depend on time, won't run faster or slower if you decrease or increase the time between ticks, and don't require any timer mocks to work around slow tests. It also means that the game's ticking behavior can be controlled entirely from Timer. Want to implement the features mentioned in TODO in the reducer? Pausing the timer between turns means updating the interval registration here in Timer. In fact, pausing the timer might not even be a feature of reducer at all, depending on the chosen implementation. As long as a TICK isn't dispatched, the gamestate will not change.