Reputation: 77
How to conditionally render a server component depending on client component state?
Components in question
Get
Button
AverageSalary
What do I want to achieve
When clicking on a <button>
HTML element in the Button
component, the <h2>
HTML element should render.
Changing the state of toggleShowData
(whether it is true
or false
) in the Button
client component is the condition under which the <h2>
HTML element in the AverageSalary
server component should (not) render.
The code
Parent server component Get.js
*:
import { getAverageSalary } from "./getAverageSalary";
import AverageSalary from "./AverageSalary";
import Button from "./Button";
export default async function Get() {
const averageSalary = await getAverageSalary();
return (
<>
<Button />
<AverageSalary data={averageSalary} />
</>
);
}
Child client component Button.js
:
"use client";
import { useState, useEffect } from "react";
export default function Button() {
const [toggleShowData, setShowData] = useState(false);
useEffect(() => {
console.log(toggleShowData);
}, [toggleShowData]);
function handleClick() {
setShowData(true);
}
return <button onClick={handleClick}>GET average salary</button>;
}
Child server component AverageSalary.js
:
export default async function AverageSalary({ data }) {
return (
<>
{/* Conditionally show this element */}
<h2>{data}</h2>
</>
);
}
*Utility function getAverageSalary.js
(used for data fetching):
import "server-only";
export async function getAverageSalary() {
const res = await fetch(`http://localhost:3001/`);
return res.text();
}
Upvotes: 0
Views: 81
Reputation: 624
Use css. There's really no way to send data upwards from a client component to a server component apart from manipulating the DOM after both have rendered. There are some cases where you can use search parameters or cookies, but it doesn't seem like that would fit in this case. If you don't want things to flash when they should be hidden, use an initial class that hides it and then set it to what it should be in the client's useEffect
hook, or if you want to show it initially just add a second 'hidden' state and set that based on user interaction.
Upvotes: 1