-
-
Notifications
You must be signed in to change notification settings - Fork 571
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
Imperatively refresh atomFamily #71
Comments
@fkocovski Hi, nice to see you trying
Would you create a small repro in codesandbox?
Please consider using Maybe related: #68 |
Here is a small codesandbox in which I managed to reproduce the error. Please note that the async |
Thanks for the repro. It seems to reproduce the error with Meanwhile, if you have a question about using |
Thanks for the prompt feedback @dai-shi , for the moment I reverted as per your suggestions to the The library is truly a game-changer, I love the streamlined APIs, I've started integrating it in one of our projects ;) Looking forward to all the new features in the pipeline, keep up the amazing work. |
Yeah, suspending on write is very tricky. For now, the atom you invoke |
https://codesandbox.io/s/elastic-cloud-zj3fe The idea is to have a normal const fetchData = atom(async (get) => {
const data = await fetch("https://jsonplaceholder.typicode.com/posts");
return await data.json();
}); and then having a normal component with export default function App() {
const [data] = useAtom(fetchData);
const newPost = async () => {
await fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST",
body: JSON.stringify({
title: "foo",
body: "bar",
userId: 1
}),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
});
};
return (
<>
<div>
<button onClick={newPost}>new</button>
</div>
<div>
<ol>
{data.map((x) => (
<li key={x.id}>{x.title}</li>
))}
</ol>
</div>
</>
);
} What I still struggle is with the |
If we could make the initial data empty, and fill it with useEffect on mount, it should be easy. I have one idea, which may not seem perfect, but it works. (I really enjoy this Jotai puzzle!) |
I like your approach. For the moment I decided to stick to the empty |
I really like this library! While I'm still trying the figure out its quirks, I figured solving a puzzle is a good way to learn. Here is my attempt at it: https://codesandbox.io/s/cool-firefly-xhyc2 Is it a good way to solve that problem? I'm wondering whether (PS it seems codesandbox's refresh and Jotai don't play along well, you might get the atom state not found. possibly a bug. error after editing the code, but it'll work fine after reloading the in-page browser... still I'm curious what might cause it.) |
const postsAtom = atom(fetchPosts());
const latestPostsAtom = atom(
(get) => get(postsAtom),
async (_get, set) => set(postsAtom, await fetchPosts())
); Mind blown! 🤯
Half expected. Atom references are important, so when it changes with React Fast Refresh, it will work somewhat unexpectedly. By splitting files, it may be improved. |
I was wrong. The promise in the primitive atom is resolved before render just like the derived atom. So, it works without the pitfall. |
I don't think it's resolved before render, it's the |
Yep. That's correct. I mean, it's the library that let |
I'm not sure what to do with this issue. It seems too technical and edge use cases to write it in the current docs. Suggestions? |
@fkocovski why don't you just do something like this, export const refreshAtom = atom(false);
const fetchData = atom(async (get) => {
get(refreshAtom);
const data = await fetch("https://jsonplaceholder.typicode.com/posts");
return await data.json();
});
export default function App() {
const [refresh, setRefresh] = useAtom(refreshAtom);
const [data] = useAtom(fetchData);
const newPost = async () => {
await fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST",
body: JSON.stringify({
title: "foo",
body: "bar",
userId: 1
}),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
});
setRefresh(!refresh);
};
return (
<>
<div>
<button onClick={newPost}>new</button>
</div>
<div>
<ol>
{data.map((x) => (
<li key={x.id}>{x.title}</li>
))}
</ol>
</div>
</>
);
} |
Hey @pyros2097 thanks for the input. That is however exactly what I wanted to avoid: creating a dummy atom to refresh the async call. Meanwhile using the set part works flawlessly for me and I am using that approach to refresh async atoms. |
current status:
This issue is still open for suggestions. I think we could either add notes in docs or create a new util. Any volunteers? |
While working on #304, I found this is not super nice. It currently works with undocumented behavior, but TS typing does not support for this use case. We are getting used to handling async (#248), so there would be a better way. Closing this as not recommended for now. Please open a new issue with a use case to discuss further. |
What would be the best way to imperatively refresh an
atomFamily
?Let's say I have following case, where I use
get(updateAtomFamily)
in order to track it as dependency in theatomFamily
so that I trigger the fetch imperatively:Then my idea was to imperatively
useUpdateAtom
in my component as a refresh function like this:and then have the imperative call:
However, when I trigger the refresh function, I get following error:
In my opinion however, even if this approach worked, it feels sluggish and cumbersome to me. It would be extremely helpful if the API had a native approach to re-fetch async atoms :)
The text was updated successfully, but these errors were encountered: