I have a search textbox with comma-separated search terms. In order to append a new search term, I'd like to use a selector to avoid re-implementing the append logic. Currently, I use the setter of a selector but since the getter is mandatory, I have to implement it as well. Below you can find the current implementation (simplified). My question: I'm not happy with it since all I need is a write-only selector but I have to implement the get. Do you have a suggestion on how to implement this use-case in a better way?
export const searchStringState = atom<string>({
key: 'searchStringState',
default: '',
});
export const searchTermsState = selector<string[]>({
key: 'searchTermsState',
get: ({ get }) =>
get(searchStringState)
.split(',')
.filter(Boolean)
.map((x) => x.trim()),
});
// since I want to call the selector with a string, I have to implement the getter with `searchStringState`,
// otherwise TypeScript would complain that `string` and `string[]` aren't compatible.
export const appendSearchTermState = selector<string>({
key: 'appendSearchTermState',
get: ({ get }) => get(searchStringState),
set: ({ get, set }, newValue) => {
const currentSearchString = get(searchStringState);
const currentSearchTerms = get(searchTermsState);
set(
searchStringState,
`${currentSearchString}, ${newValue}`,
);
},
});
I'd just make a generic hook.
export default function useSearchStringApi() {
const setSearchString = useSetRecoilValue(searchStringState);
return {
append: (str: string) => setSearchString(search => search + ',' + str);
// can also add other stuff like get value or remove a substring or stuff like that
}
}
Thanks @BenjaBobs! Yup, using simple hooks here is great for constructing an API and there shouldn't be a need for the write-only selector node for this use-case. That helps avoid the overhead of complicating the data-flow graph of atoms/selectors. For more complex API, you could also use useRecoilCallback() which allows reading/writing to dynamically determined atoms/selectors. But, always a good idea to keep it simple if you can.
Yeah, thanks a lot @BenjaBobs! I've been so focussing on following the recoil way I completely overlooked the obvious way ^^
Most helpful comment
Thanks @BenjaBobs! Yup, using simple hooks here is great for constructing an API and there shouldn't be a need for the write-only selector node for this use-case. That helps avoid the overhead of complicating the data-flow graph of atoms/selectors. For more complex API, you could also use
useRecoilCallback()which allows reading/writing to dynamically determined atoms/selectors. But, always a good idea to keep it simple if you can.