I faced with the required code in selector to implement common setter only to trigger other states.
Business case:
I have multiple places where I need to cleanup my form values and then reset my state to not dirty.
const textState = atom({key: '1', default: ''});
const dropdownState = atom({key: '2', default: 'valueId'});
const dirtyState = atom({key: '3', default: false});
const resetState = selector({
key: '4',
get: () => {}, // redundant but required,
set: ({set}) => {
set(textState, '');
set(dropdownState, 'valueId');
set(dirtyState, false);
}
})
and in the components where the logic must be called:
const Component = () => {
const resetState = useSetRecoilStat(resetState);
return <button onClick={resetState}>click me</button>;
}
Request: add new entity with opportunity to use only setter like initial trigger of state reactions.
const resetStateSetter = power<TypeOfValueToSet>({
key: '4', // maybe is redundant for public API
set: ({set}, value: TypeOfValueToSet) => {
set(textState, '');
set(dropdownState, 'valueId');
set(dirtyState, false);
}
})
I named it after quick look as power like smt abstract affects/triggers atoms (temporary name)
Do you really need a selector here? How about just making a hook:
const useResetState = () => {
const setTextState = useSetRecoilState(textState);
const setDropdownState = useSetRecoilState(dropdownState);
const setDirtyState = useSetRecoilState(dirtyState);
return () => {
setTextState('');
setDropdownState9('valudId');
setDirtyState(false);
};
};
or, useRecoilCallback():
const resetState = useRecoilCallback(({set}) => () => {
set(textState, '');
set(dropdownState, 'valueId');
set(dirtyState, false);
}, []);
Looks fine, only one point I want to highlight: this approach is placed under React more than Recoil and on my point is not consistent.
I mean we have default chain of actions are fired step by step started with initial signal (any setter) and in this case we have two different ways for the same result.
want to initiate state changes
do we have values (state) in initial setter
? let directly use setter with updated value
: let perfrom smt other like custom hook or useRecoilCallback
As end-user it could be not obvious to perform different solutions for the same goal.
Moreover all state manipulation initially are placed in derived states (selectors) and for some reason I need to place the same logic out.
So the possible solutions with custom hooks or callback usage for me looks like the workaround.
Anyway proposed options will work as need and the goal of this request will be more an answer to the question. Is missed posibility to initiate state changes with only setter call is gap with a lot of workarounds or recoil's feature?
p.s. any option will be fine for me.
Yeah, the Recoil philosophy is to try to be minimal and rely on React functionality as much as possible. So, using hooks or such when it makes sense. Selectors are conceptually meant to represent derived state, so just using them to update multiple atoms is more like a workaround. But, we can just use React approaches like hooks or callbacks for that. Or, if we also need to interrogate other state then using a Recoil callback which extends callbacks to be able to access Recoil state.
Most helpful comment
Do you really need a selector here? How about just making a hook:
or,
useRecoilCallback():