I'm working with the latest version of Next.js (version 14) and have a scenario where I'm using both Server and Client Components.
In my setup, a ServerComponent renders a dropdown list with options fetched from an API. I need to capture the selected value from this dropdown in a ClientComponent and store it in the state of the client component.
However, I'm not sure how to properly pass the value from the server-side component to the client-side component. Below is the code I have so far:
// ServerComponent.js
import { fetchOptions } from "@/app/lib/data";
export default async function ServerComponent() {
const options = await fetchOptions('');
const handleChange = () => {
console.log('save the value in father client component');
}
return (
<main>
<div>
<h2>Dropdown</h2>
<select name="myDropdown" onChange={handleChange}>
<option value="">--Choose--</option>
{options.map((option) => (
<option key={option.id} value={option.id}>
{option.nombre}
</option>
))}
</select>
</div>
</main>
);
}
// ClientComponent.js
'use client';
import { useState } from 'react';
export default function ClientComponent({ params, children }) {
const [option, setOption ] = useState();
// how can I receive and save in this client component
// the onChange value from children which is Server Component
return (
<main>
{children}
</main>
);
}
What I've tried: I've set up a handleChange function inside the ServerComponent, but I'm struggling to find the correct way to pass the selected value back to the ClientComponent and store it in its state.
Question: How can I pass the onChange value from the ServerComponent to the ClientComponent and store it in the state in Next.js 14? Is there a recommended approach for this, or am I missing something fundamental about the interaction between Server and Client Components in this version?
You should alter them by putting the client component inside the server compnent and pass the value of fetch as prop
ServerComponent.js:
import default async function ServerComponent() {
const options = await fetchOptions(); // no '' in parentheses
return (
<main>
<div>
<h2>Dropdown</h2>
<ClientComponent options={options} />
</div>
</main>
);
}
ClientComponent.js:
'use client';
import { useState } from 'react';
export default function ClientComponent({ params, options}) {
// options is an array from serverCompoent
const handleChange = (event) => {
console.log('save the value',event.target.value);
}
return (
<main>
<select name="myDropdown" onChange={handleChange}>
<option value="">--Choose--</option>
{options.map((option) => (
<option key={option.id} value={option.id}>
{option.nombre}
</option>
))}
</select>
</main>
);
}