3
votes

I've made an angular service to share state data across multiple components in my application. In order to share, it has a BehaviorSubject that can be subscribed to

export class DesignerService {
  private selectedFieldBehavior: BehaviorSubject<FormField> = new BehaviorSubject(this.selectedField);

  getSelectedField(): Observable<FormField> {
    return this.selectedFieldBehavior.asObservable();
  }
}

Multiple components subscribe to this via the getSelectedField() method. When I use next() to send a new object ( this.selectedFieldBehavior.next({ object }) ) , if any component subscribing to it modifies a property, all the subscribing components see that modification without notifying the service (like it's sending a reference instead of a copy), thus allowing the individual subscribers to modify each other's data

I've done a bit of work with angular/redux in the past, and I thought they promoted one-way dataflow and immutability. Reducers were the only way to modify the state, and then changes were propogated downwards to the subscribing components. What I currently have will allow child component to modify whatever they want. I'm not super experienced with building large angular apps that require state management. Am I mis-understanding how state management should work?

1
have you tried to clone the object? copy by value? - itdoesntwork
how/where would you do that? in the service, or in each component that is subscribing? - Will
Made some edits to the question to make it hopefully easier to understand what I'm asking - Will
like it's sending a reference instead of a copy: well, that's exactly what it does. References to objects are passed in JavaScript. That's how it works. I thought they promoted [...] immutability: yes, and you chose not to use an immutable object, but a mutable one instead. emit an immutable object, and nobody will be able to mutate it. - JB Nizet
@JBNizet is there a method/library you'd suggest for that? - Will

1 Answers

3
votes

You can change your method a bit to return a clone

getSelectedField(): Observable<FormField> {
  return this.selectedFieldBehavior.asObservable().map(obj=>Object.assign({},obj));
 }