react-request-hook icon indicating copy to clipboard operation
react-request-hook copied to clipboard

SSR support

Open jerrygreen opened this issue 5 years ago • 1 comments

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 to useEffect but isn't a hook
  • Nor it's a part of rendering function, so I can't use hooks inside (like, useResource or useRequest; however, logically it's part of render, but because of SSR, it should be separated)

What do we do?

To resume, there two cases:

  1. The app opened initially, and request is handled by the server - getInitialProps is called by server, hook shouldn't be applied
  2. 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:

  1. 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's useResource
  2. 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.

jerrygreen avatar May 09 '19 10:05 jerrygreen

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

jerrygreen avatar Nov 28 '19 15:11 jerrygreen