Make XHR requests using ObervableResource with a parameter
MaximeBernard opened this issue · 4 comments
Hi @crimx,
thanks a lot for this project!
I'm trying Render as you fetch suspense but I'm having issues with ObservableResource when I need to "create them inside components".
Basically I have
const r = new ObservableResource(ajax.get(API_URL));
but sometimes, I'm using routing which is mixed into the API_URL
const { id } = useParams();
const r = new ObservableResource(ajax.get(API_URL + '/' + id));
In this case:
- if I create my
ObservableResource
inside the child component (where IuseObservableSuspense(r)
, I get infinite loop (I think I get why) - if I create my
ObservableResource
inside the parent component and pass it to the child component (where I<Suspense...></Suspense>
), I get 2 calls (I don't really understand why)
What do you suggest? I couldn't find any example using ajax
from rxjs
. Do you have any? What do you think overall about the approach?
Thank you for your time.
You cannot create Suspense resource inside Component that comsumes the resource. It will trigger the Suspense which destroys the Component and itself hence the infinite loop.
if I create my ObservableResource inside the parent component and pass it to the child component (where I <Suspense...>), I get 2 calls (I don't really understand why)
It was not supposed to. Do you have React StrictMode
turned on? It will cause many unwanted calls.
It's hard to say without seeing the code.
I couldn't find any example using ajax from rxjs. Do you have any?
See the example:
observable-hooks/examples/suspense/src/index.tsx
Lines 5 to 10 in beeb7c0
It does not matter how you do ajax. Just export the API that will trigger ajax calls to the Component.
You cannot create Suspense resource inside Component that comsumes the resource. It will trigger the Suspense which destroys the Component and itself hence the infinite loop.
Makes more sense, thank you 👍
if I create my ObservableResource inside the parent component and pass it to the child component (where I <Suspense...>), I get 2 calls (I don't really understand why)
It was not supposed to. Do you have React
StrictMode
turned on? It will cause many unwanted calls.
YES! This was the reason. Removing StrictMode solves the issue. Explaination here
Thank you for pointing me in the right direction 👍
It does not matter how you do ajax. Just export the API that will trigger ajax calls to the Component.
I can't export the Observable
like you do because I don't know the (REST) resource (/users/1
or /users/2
?) until I'm in the component.
I could have gone both ways:
- Using a
Subject
and feeding the:id
in the observable of the requested resource as soon as I have it - Creating the observable on the fly in the parent component and passing it to the child component
I've chosen 2. because it's simpler and less verbose but I'm concerned about having to pass the "ObservableResource" to the child component. It doesn't seem right.
Right now, I'll probably create some HOC to encapsulate all that logic (Suspense + ObservableResource creation). Have you considered such a thing in observable-hooks
?
Last question: have you considered creating a hook instead of calling new ObservableResource()
directly? We'd probably benefit from useMemo
?
I can't export the Observable like you do because I don't know the (REST) resource (/users/1 or /users/2?) until I'm in the component.
I am not exporting Observable either. Take a look at the example especially:
observable-hooks/examples/suspense/src/index.tsx
Lines 26 to 27 in beeb7c0
setUserId(id)
fetchProfileData(id)
I don't know the id
until the exported API is called.
The idea is to turn API parameters to an Observale and then switchMap
it to an Observable of ajax results.
Right now, I'll probably create some HOC to encapsulate all that logic (Suspense + ObservableResource creation). Have you considered such a thing in observable-hooks?
Last question: have you considered creating a hook instead of calling new ObservableResource() directly? We'd probably benefit from useMemo?
Creating resource inside the Component goes against the design of Suspense. I haven't came up with a good pattern for this.
The idea is to turn API parameters to an Observale and then
switchMap
it to an Observable of ajax results.
Yes, that's what I had in mind with Option 1. but it seems too verbose.
Creating resource inside the Component goes against the design of Suspense.
No I meant "creating resource in the parent component and pass it through props to the child component".
I haven't came up with a good pattern for this.
Yeah me neither. At the end so I gave up Suspense
and chose to create my own hook:
const useAjaxState = <T>(url: string, initialState: T): T => {
const ajax$ = useObservable(() =>
ajax.get<T>(url).pipe(map((r) => r.response)),
);
return useObservableState(ajax$, initialState);
};
// usage
export const DisplayUser = (): ReactElement => {
const users = useAjaxState<readonly User[]>(
API_URL + '/users/1',
[],
);
return (
<div>
<h1>User {user.id}</h1>
<pre>{JSON.stringify(user)}</pre>
</div>
);
};
Thank you again for your time.