Reputation: 411
In my next.js app I have a page with two components: A
and B
.
// page.tsx
import A from './A'
import B from './B'
const Page = () => {
return (
<div>
<A />
<B />
</div>
)
}
export default Page
// A.tsx
'use client';
import { useState } from 'react'
const A = () => {
const [count, setCount] = useState(0)
return (
<div>
<p>you clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>click me</button>
</div>
)
}
export default A
// B.tsx
'use client';
import { useState } from 'react'
const B = () => {
const [count, setCount] = useState(0)
return (
<div>
<p>you clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>click me</button>
</div>
)
}
export default B
Let's assume that I want to render Page
statically on the server. However, I also would like to implement state on the client side. What is the best way to synchronize the state of A
and B
while keeping Page
as a server component?
Upvotes: 4
Views: 1007
Reputation: 31
You can make use of the context API for that. You can render your context provider it in a client component and inject it in your page:
// page.tsx
// ...
const Page = () => {
return (
<MyProvider>
<A />
<B />
</MyProvider>
)
}
// ...
The context can look something like this:
// CountProvider.tsx
"use client";
interface CountContextType {
count: number;
setCount: Dispatch<SetStateAction<number>>;
}
export const CountContext = createContext<CountContextType>({
count: 0,
setCount: () => {},
});
export default function CountProvider({children}: {children: React.ReactNode}) {
const [count, setCount] = useState<number>(0);
return (
<CountContext.Provider value={{ count, setCount }}>
{children}
</CountContext.Provider>
);
}
Finally, you can access and modify the same context count from your child components, effectively sharing the state. For example, in the component A
, instead of using:
const [count, setCount] = useState(0);
You can use:
const {count, setCount} = useContext(CountContext);
Upvotes: 2