Skip to main content

Server & Client

As said, Next.js executes pages by default at the server level. So React hooks cannot be used since they are client-side only and rely on the browser's window object (or better even: the DOM).

Although you can use client-side and server-side components together, you should be aware of the hierarchy of the components and the way they are rendered.

Differences between server-side and client-side components

In (plain) React, you can use the useEffect hook to run code on the client side. In Next.js, you can just execute an async function in the page:

React
import {useState, useEffect} from "react";

const App = () => {

const [data,setData] = useState(null);
const [isLoaded, setLoaded] = useState(false);

useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(data => {
setData(data)
setLoaded(true)
});
}, [])

return (
<div >
<code>
{ isLoaded && JSON.stringify(data) }
</code>
</div>
)
}

export default App;

Next.js

const Page = async () => {

const data = await fetch('https://jsonplaceholder.typicode.com/posts')
const response = await data.json()

return (
<div >
{ JSON.stringify(response) }
</div>
)
}

export default Page;

Calling client-side code from server-side code

If you want to use a client side component inside a server side Page, you can simply import the component and use it. You just need to flag the client side component as use client at the top of the file:

Client Component

'use client'

import {useState, useEffect} from "react";

const Client = () => {

const [data,setData] = useState(null);
const [isLoaded, setLoaded] = useState(false);

useEffect(() => {

const info = []

fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(data => {
setData(data)
setLoaded(true)
});
}, [])

return (
<div >
<h1>Client</h1>
<code>
{ isLoaded && JSON.stringify(data) }
</code>
</div>
);
}

export default Client

Server Page

import Client from '../components/Client'

const Home = async () => {
return (
<div >
<Client />
</div>
)
}

Passing data from server to client

You can pass data from the server to the client by providing the props to the client component:

Server Page

import Client from '../components/Client'

export default async function Home() {

const data = await fetch('https://api.dev-master.ninja/reactjs/slow/')
const response = await data.json()

return (
<div >
<Client data={response} />
</div>
)
}

Client Component

'use client'

const Client = ({data}) => {

return (
<div >
<h1>Client</h1>
<code>
{ JSON.stringify(data) }
</code>
</div>
)
}

export default Client