-
-
Notifications
You must be signed in to change notification settings - Fork 581
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
RESET symbol should be exported from jotai/utils #217
Comments
Hmmmm, I see your use case... but, I hesitate exporting the symbol. Would like to hide it as an implementation detail. |
Yes, exporting just the type is what this code does:
but the problem then becomes that there's no clear way to implement Recoils In a sense, if RESET is not exported it is easier to implement your own Having said all of that :) I only decided to try out
|
I similar to
|
As for typing, does this work? type ExtractAtomUpdate<T> = T extends WritableAtom<unknown, infer U> ? U : never
type TypeOfRESET = Exclude<ExtractAtomUpdate<typeof tempFahrenheitAtom>, number>
OK, let's keep this issue open for a while to gather more use cases, and then consider what to do.
I don't think That said, I'm happy to have |
makes sense.
I got to the same conclusion once I looked more into it :)
I agree with that :) it's just a shame that you would have to reimplement
I think a solution that gets us 90% there is to export RESET type (note that it's no longer import { atom } from "jotai";
import { atomWithReset, RESET } from "jotai/utils";
export const tempFahrenheitAtom = atomWithReset(32);
export const tempCelciusAtom = atom(
(get) => ((get(tempFahrenheitAtom) - 32) * 5) / 9,
(get, set, newValue: number | RESET) =>
set(
tempFahrenheitAtom,
typeof newValue === "symbol" ? newValue : (newValue * 9) / 5 + 32
)
);
// in component
const reset = useResetAtom(tempCelciusAtom); and adding import { atom } from "jotai";
import { atomWithReset, RESET, isReset } from "jotai/utils";
export const tempFahrenheitAtom = atomWithReset(32);
export const tempCelciusAtom = atom(
(get) => ((get(tempFahrenheitAtom) - 32) * 5) / 9,
(get, set, newValue: number | RESET) =>
set(
tempFahrenheitAtom,
isReset(newValue) ? newValue : (newValue * 9) / 5 + 32
)
);
// in component
const reset = useResetAtom(tempCelciusAtom); when I'm talking about getting 100% there I mean something like this: import { atom } from "jotai";
import { atomWithReset, RESET } from "jotai/utils";
export const tempFahrenheitAtom = atomWithReset(32);
export const tempCelciusAtom = atom(
(get) => ((get(tempFahrenheitAtom) - 32) * 5) / 9,
(get, set, newValue: number | typeof RESET) =>
set(
tempFahrenheitAtom,
newValue > 100 ? RESET : (newValue * 9) / 5 + 32
)
);
// in component
const [, set] = useAtom(tempCelciusAtom);
set(999); which would be the same as Recoil's: newValue > 100 ? (new DefaultValue()) : (newValue * 9) / 5 + 32 Returning back to the extensibility of atomWithReset, since resetting in Recoil is the first-class citizen you can actually do this: export const tempCelcius = selector<number>({
key: "tempCelcius",
get: ({ get }) => ((get(tempFahrenheit) - 32) * 5) / 9,
set: ({ set, reset }, newValue) =>
newValue instanceof DefaultValue
? reset(tempFahrenheit)
: set(tempFahrenheit, (newValue * 9) / 5 + 32)
}); so last piece of the puzzle could be exporting type of import { atom } from "jotai";
import { atomWithReset, RESET, isReset, reset } from "jotai/utils";
export const tempFahrenheitAtom = atomWithReset(32);
export const tempCelciusAtom = atom(
(get) => ((get(tempFahrenheitAtom) - 32) * 5) / 9,
(get, set, newValue: number | RESET) =>
isReset(newValue)
? reset(set, tempFahrenheitAtom)
: set(tempFahrenheitAtom, (newValue * 9) / 5 + 32)
);
// in component
const reset = useResetAtom(tempCelciusAtom); but at what point we could agree that this is over-engineering and it's easier to just export the RESET symbol? :-D |
wow, your consideration is really thorough. It's clear that you make good points. |
I just ran into a similar need for resetting an atom through the setter, and having access to either the const searchAtom = atomWithReset('');
const timelineAtom = atomWithReset(0);
const categoryAtom = atomWithReset('random');
// The value is used in a single component for a GraphQL query, while the set is used from multiple components.
// Only one filter can be set at a time, but they are stored in separate atoms to reduce renders since multiple
// components will depend on each of the individual atoms, and so that derived atoms don't need to know
// about the other types of filters
const filterAtom = atom(
(get) => {
if (get(searchAtom)) { return { search: get(searchAtom) }; }
if (get(timelineAtom)) { return { timeline: get(timelineAtom) }; }
return { category: get(categoryAtom) };
},
(get, set, [type, value]) => {
set(searchAtom, type === 'search' ? value : RESET);
set(timelineAtom, type === 'timeline' ? value : RESET);
set(categoryAtom, type === 'category' ? value : RESET);
},
);
// In the search component
const [searchValue] = useAtom(searchAtom);
const setFilter = useUpdateAtom(filterAtom);
...
setFilter(['search', 'some value']);
// In the component that runs the query
const [filterValue] = useAtom(filterAtom); // { search: 'some value' }; This setup would allow my components to use the |
@SpenserJ Thanks for chiming in. As the use case is clear, and users are not confused, exporting |
Here's the code that I want to write:
I created a sandbox that has an example of the code and possible workarounds https://codesandbox.io/s/jotai-atom-with-reset-bug-k6xcu?file=/src/atoms2.ts as well as recoil analog
The text was updated successfully, but these errors were encountered: