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