SSR
Server-side-rendering is supported out-of-the-box. When you set a default
value in useFetch
, it will also be server-side-rendered.
Because fetching with useFetch
doesn't work on the server-side, you can use the Client
object, which is very similar to Axios
(opens in a new tab) but sends the request using fetch
instead of an XMLHttpRequest
. In case you want to re-use it, it has an extend
property (similar to axios.create
)
Example using Next.js's getServerSideProps
(opens in a new tab):
import useFetch, { Client } from 'http-react'
// It works inside server and client components
const api = Client.extend({
baseUrl: 'https://my-api.com',
headers: {
Authorization: 'Token etc'
}
})
export async function getServerSideProps(context) {
// 'loading' does not work here
const { data } = await api.get('/api/user')
return {
props: {
user: data
} // will be passed to the page component as props
}
}
export default function MyPage({ user }) {
const { data } = useFetch('/api/user', {
default: user
})
return (
<div>
<h2>Welcome, {data.name}</h2>
</div>
)
}
With Server Components in Next.js:
This part covers server-side rendering with Next.js ^13.0.0 (with server components). They work in a differente way from client components. The main difference is that Server components don't ship any JavaScript to the client, thus they are not interactive. This means that things such as useState
or createContext
don't work directly inside them. However, they can run server-only code, making them perfect for things like layouts, or user-authentication. Let's look at an example of data fetching in the server using http-react
Inside the main layout as a server component:
import { cookies } from 'next/headers'
import { FetchConfig, Client } from 'http-react'
import Login from 'components/Login'
export default async function Layout({ children }) {
// This is only works in server components!
const appSession = cookies().get('appSession')?.value
const baseUrl = 'https://my-website.com/api'
const headers = {
Authorization: 'Token ' + appSession
}
// Creating a client
// (we can't pass a fetcher function because functions can't be serialized!)
const api = Client.extend({
baseUrl,
headers
})
// This works everywhere
const { data, error } = await api.get('/auth')
if (error) return <Login />
return (
<FetchConfig
baseUrl={baseUrl}
headers={headers}
defaults={{
'GET /api/profile': {
value: data // This will be SSR!
}
}}
>
{children}
</FetchConfig>
)
}
Inside pages/profile.tsx
:
'use client' // This marks this component as a client component
import useFetch from 'http-react'
export default function Profile() {
const { data } = useFetch('/api/profile') // Data will be preloaded here!
return (
<div>
<h2>Name: {data.name}</h2>
</div>
)
}