react-request-hook
react-request-hook copied to clipboard
SSR support
TL;DR: It's not possible to access response object Server Side, since with Server Rendering the render function is called only once (hooks doesn't really work)
I use nextjs for Server-Side Rendering purposes. react-request-hook
is beautiful for typical SPA (without prerendered components) but I feel lack of functionality for SSR use case. So further explanations are related to the case when some of components are prerendered, receive some initial props/data.
I believe you may fully understand the problem if you try it yourself. But I don't demand anything. Just gathering the info here.
The problem
At first glance you may even think you don't need react-request-hook
with nextjs because of getInitialProps
- but it's wrong. And I'm still using useResource
- it's useful to handle pagination, send forms, etc. Just doesn't suit the initial data load for SSR case. And I want to handle it properly, to use the approach similar to the react-request-hook
. Make them work together nicely.
Why initial data load should be handled differently
Theoretically hooks can be applied server-side - it's no error. But it doesn't make much sense since server does only a single render, and what's returned - it passed to the client as HTML, so you have to pass such logic like requests into getInitialProps
function
What's the way to apply react-request-hook
?
Right now, there's no way. That's what the issue is about.
- I have
getInitialProps
which is similar touseEffect
but isn't a hook - Nor it's a part of rendering function, so I can't use hooks inside (like,
useResource
oruseRequest
; however, logically it's part of render, but because of SSR, it should be separated)
What do we do?
To resume, there two cases:
- The app opened initially, and request is handled by the server -
getInitialProps
is called by server, hook shouldn't be applied - The app is already opened before you've got the page, i.e. you've been redirected (by clicking a link or sending a form, etc.) -
getInitialProps
is called by client
I was thinking how to handle this properly. I think there's two possible ways:
-
getInitialProps
makes some request only server-side (first case), while for client render (second case) it returns nothing, just allows to do all the work to the render'suseResource
-
getInitialProps
makes some request for both, server-side and client-side
I've spent some time and concluded the first way is preferable. You can't return a function with getInitialProps
(it's sent as JSON, and the function is cut, you may sent it as text and eval but fuck it).
So getInitialProps
(getInitialPropsBy
) should duplicate some functionality of useResource
but shouldn't be a hook. And of course, it should receive axios instance as an argument (since there's no way to access store provider on server-side)
Ok...
So I ended up with a function, which API is similar to useResource
– getInitialPropsBy
Cool, you have it, what else do you want?
getInitialPropsBy
should still live in peace with useResource
.
Right now I can't optionally pass the second argument to the useResource
like:
const [response, getData] = useResource(Api.posts, initialResponse ? undefined : [initialParams])
You'll get this:
But I don't even want to. Not sure.
Instead, we may add a third boolean argument which tells us if the initial data is already passed to props. So the code will look like this:
const [response, getData] = useResource(Api.posts, [initialParams], Boolean(initialResponse))
I'll make a PR later.
Huh, quite a few months passed. I've found another similar library called SWR, from NextJS devs.
It's in some ways simpler, doesn't have cancel option but they've solved this problem, it's possible to pass initialData
:
https://github.com/zeit/swr#ssr-with-nextjs