Stabilizing Callbacks and Intervals

In the previous lesson, you memoized derived values with useMemo to avoid extra work during the 1-second TICK loop. Earlier, you also split Context and used React.memo to reduce re-renders.

In this lesson, you will stabilize the game loop and event handlers with useCallback and carefully scoped useEffect hooks. A common mistake is to include changing state (like the current time) in the dependency array of your tick handler. This forces the interval to be torn down and recreated every second, which is bad for performance.

To fix this, we separate the mechanism of ticking from the logic of checking the game state.

Stabilize the game loop in GameScreen

We create a stable handleTick that only dispatches the tick action. It depends only on dispatch, so it never changes. We then use one effect to run the interval, and a separate effect to check if the shift is over.

Explanation:

  • handleTick is memoized and stable because it doesn't read changing state.
  • The interval effect depends only on phase, isPaused, and the stable handleTick. It stays active without resetting every second.
  • The game-over check runs in its own effect whenever the time changes, keeping the concerns separate.
Freeze HUD button handlers

Explanation:

  • The pause/resume handler has a stable reference. When passed to children, it will not change across renders unless dispatch changes.
  • Stable handlers reduce prop churn, which is helpful when combined with React.memo.
Efficient action dispatchers in GameActions

Explanation:

  • This factory returns a stable click handler per action type because its only dependency is dispatch.
  • It pairs well with the memoized ActionButton, so buttons re-render only when their enabled state (or other relevant props) changes.
Summary and next steps

You stabilized the game loop and user interactions by:

  • Using useCallback to keep dispatching functions stable.
  • Separating the interval logic from the state-checking logic to prevent "interval thrashing."
  • Returning cleanups to avoid memory leaks.

This completes your rendering performance toolkit. You have split Context, memoized components and values, and now stabilized callbacks and intervals. Get ready to put this into action in the practice section and feel how smooth the game becomes.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal