angularsignalseffectangular17

How to correctly use Angular signal effect with arrays?


I’m trying to use the new angular signal effect to listen on changes for a signal array of objects.

But the effect doesn’t get called at any time.

It gets only called if I filter out one object of the array. Pushing and updating an object of the array doesn’t call the effect.

Here’s my code:

// this code trigger the effect
case "DELETE":
          this.houses.update(((houses: House[]) => houses.filter((house: House) => house.id !== payload.old.id)));
          break;
// this code doesn’t trigger the effect
        case "INSERT":
          this.houses.update((houses: House[]) => {const updatedHouses = houses.push(payload.new); return updatedHouses;})
          break;
effect(() => {
      this.filteredHouses = this.houses();
      this.onFilter();
    });

Obey of I reset the value of the signal and set the new value afterwards, the effect will be called. What am I doing wrong?


Solution

  • The effects (or change detection) won't be triggered if the object reference of the signal value is not changed. Signals use the Object.is under the hood to check for equality. This means that modifying an array in place (pushing, sorting, etc) it's not considered a "change". A simple solution for that would be to use the spread operator when you update the array, like that:

    this.houses.update(houses => ([...houses, payload.new]))
    

    Or you can pass a custom equality function to the signal, like that:

    houses = signal([], { equal: (a, b) => a.every(item => b.includes(item)) })
    

    Learn more from the Angular docs about signals