-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: use 'signalFrom' helper in services #2
Conversation
Hey thanks for the example! It's funny I also landed on pretty much that exact API too, except I called it "reducerSignal" - the downside is that with the reducers needing to be declared up front you do lose the ability for reducers to make use of existing state. I'm not sure this is a bad thing, it's kind of a good thing really, but definitely a tradeoff. Not sure if I prefer the approach or not yet, I'll have to play around some more. |
I think the |
I've been working on this a little to get it to optionally support any number of reducers. As I mentioned my starting point was almost identical to the API you've suggested here, and for now I've landed on this API for supplying different sources with different reducers: state = connectSignal(
this.initialState,
this.nextState$,
[
this.add$,
(state, checklist) => ({
checklists: [...state.checklists, this.addIdToChecklist(checklist)],
}),
],
[
this.remove$,
(state, id) => ({
checklists: state.checklists.filter((checklist) => checklist.id !== id),
}),
],
[
this.edit$,
(state, update) => ({
checklists: state.checklists.map((checklist) =>
checklist.id === update.id
? { ...checklist, title: update.data.title }
: checklist
),
}),
]
); Basically you can supply as many args as you want after the initial value, and they can either just be observables, or they can be an array containing an observable and a reducer function. I think this API is nice enough to use, though let me know if you had any other ideas. I've only done a quick prototype but the downside at the moment with this API is that I can't infer the type for the observable values from the reducers. If I use a generic for the observable value it will just use whatever the type was for the first observable/reducer array, but if you supply more than one array it will still use the type value from the first. So I've had to use any for now - not sure if there is a way around this, but my advanced TypeScript knowledge is lacking so there might be something obvious I'm missing. You can see the prototype here: https://github.com/joshuamorony/angularstart-quicklists/blob/reducerSignal/src/app/shared/utils/connectSignal.ts Anyway, let me know your thoughts if you have any - I'll run this by Chau to see if there might be any interest in incorporating it into ngxtension |
Solved the typing issue, which requires using it with this withReducer helper function (not sure I like the naming for this, but it works): state = connectSignal(
this.initialState,
this.nextState$,
withReducer(this.add$, (state, checklist) => ({
checklists: [...state.checklists, this.addIdToChecklist(checklist)],
})),
withReducer(this.remove$, (state, id) => ({
checklists: state.checklists.filter((checklist) => checklist.id !== id),
})),
withReducer(this.edit$, (state, update) => ({
checklists: state.checklists.map((checklist) =>
checklist.id === update.id
? { ...checklist, title: update.data.title }
: checklist
),
}))
); |
So this ended up taking a bit of a different path, but we ended up with something pretty cool that is going to be added to ngxtension if you're interested: ngxtension/ngxtension-platform#135 |
I think the API you ended up with seems really nice! I had something like that in mind but didn't have the time to refine the API further |
If you'd like to make the state signals more declarative, it can be achieved quite easily with a simple helper function (I named it
signalFrom
). This way to understand how the value of a state signal is calculated, the only place to look is its definitionThe idea seems really similar to #1, where the
signalFrom
is from the rxState library.