'localStorage array reset when added a new item

I'm currently working on a project where I have to store as many as players as needed into an array of players using localStorage.

I'm in fact able to register those players and modifying their data as I wish, but my problem comes when I try to register a new one, the array with its fields reset to zero. I show an example

I have this array with a player registered:

[{"name":"test","score":4,"maxScore":5}]

When I add a new player, my array becomes this:

[{"name":"test","score":0,"maxScore":0},{"name":"test2","score":0,"maxScore":0}]

So as you can see, for every single player I have , the values of score and maxScore are reset to 0, and I can't figure it out why, since I haven't worked more than 4 days with localStorage

I'm providing my code next:

home.component.html

<div class="container d-flex justify-content-center align-items-center vh-100">
  <div class="row">
    <div class="card text-dark bg-dark p-5">
      <div class="card-body">
        <h2 class="mb-3">CREATE NEW PLAYER</h2>
        <input
          class="form-control"
          type="text"
          placeholder="Player name"
          name="name"
          #name
          [(ngModel)]="player.name"
        />
        <div class="d-grid gap-2">
          <button
            class="btn btn-primary mt-3"
            type="button"
            routerLink="game"
            [disabled]="player.name === ''"
            (click)="addPlayer(name)"
          >
            JOIN
          </button>
        </div>
      </div>
    </div>
  </div>
</div>

home.component.ts

export class HomeComponentComponent implements OnInit {
  constructor(public gameService: GameService, public dataService: DataService) {}

  ngOnInit(): void {}

  player: Player = {
    name: '',
    score: 0,
    maxScore: 0,
  };

  addPlayer(name: HTMLInputElement) {
    this.gameService.addPlayer({
      name: name.value,
      score: 0,
      maxScore: 0,
    });
    this.dataService.playerName = name.value;
  }
}

game.service.ts

export class GameService {
  players: Player[];

  constructor() {
    this.players = [];
  }

  addPlayer(player: Player) {
    if (localStorage.getItem('players') === null) {
      this.players.push(player);
      localStorage.setItem('players', JSON.stringify(this.players));
    } else {
      let localStorageItem = JSON.parse(
        localStorage.getItem('players') || '[]'
      );
      let item = localStorageItem.find(
        (item: Player) => item.name === player.name
      );
      if (!item) {
        this.players.push(player);
        localStorage.setItem('players', JSON.stringify(this.players));
      }
    }
  }
}

PS: I am working with Angular, but in this case it does not affect the development of the project



Solution 1:[1]

I've made some updates to your code. In the changes I have made, the application now will add new players without resetting values. It will also rehydrate the list of players on reloading the browser. Hope this helps.

enter image description here

You can see the changes in action here: https://stackblitz.com/edit/angular-game-with-local-storage?file=src/app/game.service.ts

Solution 2:[2]

Currently, in the case that you do have an array of players, and you add a new player, the control flow goes as below. I've marked the lines of code that executes in such a case.

addPlayer(player: Player) {
>   if (localStorage.getItem('players') === null) {
      this.players.push(player);
      localStorage.setItem('players', JSON.stringify(this.players));
>   } else {
>     let localStorageItem = JSON.parse(
>       localStorage.getItem('players') || '[]'
>     );
>     let item = localStorageItem.find(
>       (item: Player) => item.name === player.name
>     );
>     if (!item) {
>       this.players.push(player);
>       localStorage.setItem('players', JSON.stringify(this.players));
      }
    }
  }

You get the players from localStorage and put that in localStorageItem and not this.players. However, when !item, you this.players.push(player) and set it in localStorage. You need to append localStorageItem in this.players as well like below: (Marked the added line with !.)

addPlayer(player: Player) {
>   if (localStorage.getItem('players') === null) {
      this.players.push(player);
      localStorage.setItem('players', JSON.stringify(this.players));
>   } else {
>     let localStorageItem = JSON.parse(
>       localStorage.getItem('players') || '[]'
>     );
!     this.players.push(...localStorageItem)
>     let item = localStorageItem.find(
>       (item: Player) => item.name === player.name
>     );
>     if (!item) {
>       this.players.push(player);
>       localStorage.setItem('players', JSON.stringify(this.players));
      }
    }
  }

Solution 3:[3]

I made it work. I changed this:

if (!item) {
        this.players.push(player);
        localStorage.setItem('players', JSON.stringify(this.players));
      }

into this:

if (item === undefined) {
        localStorageItem.push(player);
        localStorage.setItem('players', JSON.stringify(localStorageItem));
      }

And it's working perfect.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 cSharp
Solution 3 AhmedSHA256