Reputation: 6867
In my Angular app , i'm working to set up a state management logic using BehaviourSubject
So , i ve in my store file this :
myStoreData = new BehaviourSubject([])
in my actions file i ve this :
export const SAVE_DATA_IN_CONTEXT = '[User] Save user the incoming data';
So that , in the component , when needed , the method to call is this:
click(newData){
this.reducerService('SAVE_DATA_IN_CONTEXT' , newData)
}
My purpose , is that in my reducer , i won't just send to the store (behaviourSubject) the new data , but i want that it appends it with the existing one ( i doosn't want that the new value replace the existing one) :
As a result it would look like this :
data to send to BehaviourSubject (array) = existing data (array of objects) + new data (object)
my reducer looks like this , and i tried that :
public dispatchAction(actionTag: string, newDataPayload: any | null): void {
switch (actionTag) {
case ActionsTags.SAVE_DATA_IN_CONTEXT :
const newDataToSet = [...Stores.myStoreData.getValue() , ...newDataPayload ];
Stores.myStoreData.next(newDataPayload);
break;
}
Since i'm convinced that the method getValue() is a bad practise , and i won't pass by Stores.myStoreData.subscribe()
because i can't handle the unsubscription and the user click method would be repetitive (possibly the subscribe would open a new subscription each time)
I'm looking fo a better manner to do it properly (maybe change the BehaviouSubject)
Suggestions ??
Upvotes: 1
Views: 876
Reputation: 23803
As explained in some comments under your question, there are libraries for this and you should probably use them instead of reinventing the wheel.
That said, lets assume this is for learning purpose and do it anyway.
I'd recommend to embrace reactive programming and build everything as streams. Then make a super tiny layer into a service to wrap this so you can provide it through dependency injection.
For the reactive bit, I'd just have a subject that I'd pass actions to. Based onto this, I'd have a stream maintaining the state. This would look like the following:
const action$ = new Subject();
const state$ = action$.pipe(
scan((state, action) => {
switch (action.type) {
case 'some_action':
// todo: return a new state
default:
state;
}
})
);
Then if you want to provide this into a service you could simply do:
@Injectable()
export class Store {
private action$ = new Subject();
public state$ = action$.pipe(
scan((state, action) => {
switch (action.type) {
case 'some_action':
// todo: return a new state
default:
state;
}
}),
shareReplay(1)
);
public dispatch(action): void {
this.action$.next(action)
}
}
Upvotes: 1