1
resposta

[Bug] Controlar classes com Recoil - Cannot assign to read only property 'positions' of object '#<Snake>'

Olá, estou criando um jogo da cobrinha em react e gostaria de executar as ações por meio de uma classes armazenada em um atom do recoil, EX: game_controller.ts:

export const state_game_controller = atom<GameController | undefined>({
  "key": "GameController",
  "default":  undefined
})

export const useChangeSnakeDirection = () => {
  const game_controller = useRecoilValue(state_game_controller)
  return (dir:TDirections) => {
    game_controller?.changeSnakeDirection(dir)
  }
}

export const useStartGame = () => {
  const game_controller = useRecoilValue(state_game_controller)
  return () => {
    game_controller?.startGame()
  }
}

app.tsx:

export const App = () => {
  const startGame = useStartGame();

  return (
    <>
      <Board />
      <button onClick={() => startGame()}>Inicar jogo</button>
      <Control />
    </>
  );
};

Entretanto, quando inicio o jogo no botão inicar do app.tsx, recebo o seguinte erro:

Cannot assign to read only property 'positions' of object '#<Snake>'

Alguem sabe o que pode ser?

os atributos da classe game_controller estão assim:

  private canvas: HTMLCanvasElement;
  private gameboard: GameBoard
  private snake: Snake
  private apple: Apple
  private canvas_drawer: CanvasDrawer
  private loop: Loop
  private score: number

Imagino que possa tel algo a ver mas não tenho certeza

1 resposta

Olá, Antonio!

Olha, esse erro aí, o "Cannot assign to read only property 'positions' of object '#'", é bem clássico. Ele aparece quando a gente tenta mudar algo que é imutável.

Então, saca só: no React e no Recoil, quando a gente guarda um objeto no estado, a ideia é pensar nele como algo imutável. Traduzindo: nada de mexer diretamente nas propriedades dele. O jeito é criar uma cópia desse objeto e, se for o caso, fazer as mudanças na cópia.

O que esse erro tá te dizendo é que, provavelmente, você tá tentando alterar diretamente algo na classe Snake, mais especificamente essa propriedade 'positions'. E já que ela tá num atom do Recoil, essa bagunça toda acontece porque ela é, de fato, imutável.

Pra te ajudar a sair dessa:

Refatorar a classe Snake: Muda a classe Snake pra garantir que, quando você mexer no objeto 'positions' (ou em outros estados), você use métodos que devolvam novas cópias, em vez de bagunçar o original.

Cuidado com o useRecoilState: No lugar de usar o useRecoilValue, que só lê o valor, parte pro useRecoilState. Aí, quando precisar mudar algo na classe Snake, você faz uma cópia dela e coloca essa nova versão no atom.

Muda o Atom: Outra opção é não guardar as classes diretamente nos atoms. Em vez disso, fica só com os dados que você precisa e muda a lógica do jogo pra ser mais funcional, deixando a orientação a objetos de lado.

Muda a visão: Pensa em usar uma pegada mais funcional pro seu jogo, deixando as classes de lado. Foca em guardar o estado do jogo como um objeto mais simples e usa funções pra atualizar. Com isso, a gestão do estado fica mais tranquila, principalmente com o Recoil.