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
Question: Post data through API with RecoilJS #462
Comments
Here's how we accomplished it: First, our atom, which has an postData property: const PostState = atom<State>({
key: "post",
default: {
postData: null
},
}); Next a selector to set that state: export const postRequestState = selector<PostData | null>({
key: `getPostRequest`,
get: ({ get }) => {
return get(PostState).postData;
},
set: ({ set }, postData): void => {
set(PostState, (oldState: State) => ({
...oldState,
postData,
}));
},
}); And then finally an async selector to do the post, as long as postData isn't export const postResponseState = selector({
key: `$getPostResponse`,
get: async ({ get }) => {
const exportStoreData = get(PostState);
if (PostState.exportRequest) {
return await // async POST here
} else {
return false;
}
},
}); This way, as long as you don't have a post ready, the selector does nothing. However, if you update postData, the selector will immediately fire off your selector. As I'm thinking about this, another approach would be to have a component responsible for doing the fetching using an async selectorFamily. Every time you wanted to post, you'd render out a new one of these with the relevant post data. That might be a better approach. Something like this: const MakePost = selectorFamily({
get: async () => // async POST here
});
type Props = {
postData: PostData;
}
export const makePost: React.FunctionComponent<Props> = (props: Props) => {
const post = useRecoilValueLoadable(MakePost(props.postData));
React.useEffect(() => {
if (post.state === "hasValue") {
// do something with the server response here
};
}, [post]);
} |
A followup to say that I'd love to see an async setter so that we could do something much more simple like this: const postSelector = selectorFamily({
get: // whatever
set: async (params) => ({ set }) => {
const response = await postQuery(params);
set(YourAtom, // etc);
}
}); |
@adrianbw - Instead of an async post selector set, consider just using a setter for const yourPostQuery = useRecoilCallback(({set}) => async params => {
const response = await postQuery(params);
set(yourAtom, response.data);
}); |
I tried this approach, but got this error.
As I said, my data is a |
We're definitely still struggling with good patterns here. A couple scenarios:
|
Yes,
Use the updater form when setting: set(yourAtom, currentArray => [...currentArray, newEntry]); |
So I'm sure I'm being absolutely dense, but let's say I do this: const doPost = useRecoilCallback(({set}) => async params => {
const response = await postQuery(params);
set(yourAtom, response.data);
});
return (<button onClick={doPost(parms)} />); What do I do to get a loadable that I can use to watch the status of that post when I click the button? |
const loadable = useRecoilValueLoadable(yourAtom);
We're looking into the ability to be able to set an atom to a pending promise to take advantage of React Suspense. But, in the meantime, if you want the atom in a pending state during the query you could manually provide this by storing an object which contains the state and data, basically your own loadable type, and update the atom to a loading state before the |
Updated documentation for syncing Recoil state with external storage in #680 |
In
RecoilJS
docs, there is an example how to handle asynchronous data queries, but it's only about get data.Let say I have a simple state:
And a component which is a register form:
The posted data is in
FormData
. After successfully created new account, the server will send a response that containsid
andname
of the account.This response data will be set as a new state of
accountState
.How can I handle the process in
RecoilJS
?The text was updated successfully, but these errors were encountered: