reactjsnext.jsnextjs14

How to pass and store a value from a Server Component to a parent Client Component in Next.js 14?


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?


Solution

  • 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>
      );
    }