Next.js Discord

Discord Forum

Proper way to manage state between two sibling client components

Answered
Argentine hake posted this in #help-forum
Open in Discord
Argentine hakeOP
Hi everyone,
I'm new to NextJS and have been having a bit of trouble regarding state management between sibling client components. I am essentially trying to conditionally render a component in my layout, however, I wish to be able to control it using my NavBar. However, as the Layout component is always a server one, I haven't been able to figure out how to transfer and update state between the two.

Here is my code:
// layout .tsx
import React from 'react'
import Topnav from '../components/Topnav'
import NewPostForm from '../components/NewPostForm'

export default function Layout({ children }: {children: React.ReactNode}) {
  return (
    <>
    <Topnav/>
    <NewPostForm isOpen={false}/>
    <main>{children}</main>
    </>
  )
}


// topnav.tsx
import Link from 'next/link'
import React from 'react'

function Topnav() {
  return (
    <nav className=''>
        <ul className='flex flex-row gap-4 text-lg font-bold p-2 border-white border-b-2'>
            <Link href={"/"}>Home</Link>
            <Link href={"/posts"}>Posts</Link>
            <li className='ml-auto'>Login</li>
            <li>New post</li>
        </ul>
    </nav>
  )
}

export default Topnav

// newpostform.tsx
import React from 'react'
interface NewPostFormProps {
    isOpen: boolean;
}

function NewPostForm(props: NewPostFormProps) {
    if (!props.isOpen) {
        return;
    }
  return (
    <form action="">
        <input type="text" placeholder='Title'/>
        <textarea name="" id="" placeholder='Content'></textarea>
    </form>
  )
}

export default NewPostForm
Answered by aardani
export default function Layout({ children }: {children: React.ReactNode}) {
  return (
    <NavContext>
      <Topnav/>
      <NewPostForm/>
      <main>{children}</main>
    <NavContext/>
  )
}
View full answer

7 Replies

@Argentine hake Hi everyone, I'm new to NextJS and have been having a bit of trouble regarding state management between sibling `client` components. I am essentially trying to conditionally render a component in my layout, however, I wish to be able to control it using my `NavBar`. However, as the `Layout` component is always a server one, I haven't been able to figure out how to transfer and update state between the two. Here is my code: js // layout .tsx import React from 'react' import Topnav from '../components/Topnav' import NewPostForm from '../components/NewPostForm' export default function Layout({ children }: {children: React.ReactNode}) { return ( <> <Topnav/> <NewPostForm isOpen={false}/> <main>{children}</main> </> ) } js // topnav.tsx import Link from 'next/link' import React from 'react' function Topnav() { return ( <nav className=''> <ul className='flex flex-row gap-4 text-lg font-bold p-2 border-white border-b-2'> <Link href={"/"}>Home</Link> <Link href={"/posts"}>Posts</Link> <li className='ml-auto'>Login</li> <li>New post</li> </ul> </nav> ) } export default Topnav js // newpostform.tsx import React from 'react' interface NewPostFormProps { isOpen: boolean; } function NewPostForm(props: NewPostFormProps) { if (!props.isOpen) { return; } return ( <form action=""> <input type="text" placeholder='Title'/> <textarea name="" id="" placeholder='Content'></textarea> </form> ) } export default NewPostForm
you cant transfer state from the client back to the server without requesting a new request to the server
you can however, put client component in a server component that reads a client top-level context that shares the state between all of the client component that reads the context
export default function Layout({ children }: {children: React.ReactNode}) {
  return (
    <NavContext>
      <Topnav/>
      <NewPostForm/>
      <main>{children}</main>
    <NavContext/>
  )
}
Answer
Argentine hakeOP
Thank you so much @aardani, that worked!
@aardani which one?
Argentine hakeOP
I just wrapped the components that I wanted to have the ability to control the state in a context provider
And it worked