React Context — Create a Connect 4 Online Training

Now that our components are ready we will be able to connect them with the logic of our state machine. For this we will create a hook that will allow us to interact more simply with our system. We will rest React’s context system by offering the following signature in order to be able to access the necessary methods anywhere.

type GameContextType = {
  state: GameStates,
  context: GameContext,
  send: <T extends GameEvents["type"]>(event: Omit<GameEvent<T>, 'playerId'>) => void,
  can: <T extends GameEvents["type"]>(event: Omit<GameEvent<T>, 'playerId'>) => boolean,
  playerId: Player["id"],
}

We can then use this hook in the different screens that make up our application.

type LobbyScreenProps = {}

export function LobbyScreen ({}: LobbyScreenProps) {
  const {send, context, can} = useGame()
  const colors = [PlayerColor.YELLOW, PlayerColor.RED]

  const joinGame = (name: string) => send({type: 'join', name: name, playerId: name})
  const chooseColor = (color: PlayerColor) => send({type: 'chooseColor', color, playerId: color === PlayerColor.YELLOW ? 'John' : 'Marc'})
  const startGame = () => send({type: 'start'})

  const canStart = can({type: 'start'})

  return <div>
    <NameSelector onSelect={joinGame} />
    <ColorSelector onSelect={chooseColor} players={context.players} colors={colors} />
    <p>
      <button disabled={!canStart} className="button" onClick={prevent(startGame)}>Démarrer</button>
    </p>
  </div>
}