Next.js Discord

Discord Forum

Can't pass function to client component

Answered
American Bobtail posted this in #help-forum
Open in Discord
American BobtailOP
I have a page which is a server component in which I have a client component nested inside a scroll area. My dilemma is that I want my submit button to appear underneath the scroll area but I can't get the data from the client component to use the submit button nor can I pass a function to the client component as a way of submitting the data.

Does anyone know what sort of pattern I can use to either get data out of a client component into the parent server component or somehow delegate the submit buttons onClick function to the client component?
Answered by American Bobtail
My solution was to wrap the scroll area and button in a context provider. This way a client component encompasses both the scroll area and button but it also holds state. The ChecklistForm and button can then set the state in the context provider with useContext. Since the scroll area is passed to the context provider from the Page (which is server side rendered) it remains a server component
View full answer

19 Replies

Sloth bear
Can you provide code
American BobtailOP
export default async function Page({ params }: { params: { room_id: string } }) {
    const checklistItems: ChecklistItem[] = await fetchChecklistInfo(params.room_id);

    return (
        <div className="relative inset-y-8">
            <div className="flex justify-center">
                <ScrollArea className="h-[400px] w-[350px] rounded-md border p-4 shadow-xl">
                    <ChecklistForm checklistItems={checklistItems} />
                </ScrollArea>
            </div>
        </div>
    )
}
Underneath scroll area I want to add a submit button but it's useless if it can't get the data that's within ChecklistForm
I either need to somehow get the data out of the ChecklistForm component which Im pretty sure is impossible or I need to be able to give the ChecklistForm a delegate of the onClick function of the submit button
Sloth bear
You can just make a separate Client Component and add the Scroll Area and Checklist Form inside it then pass the data to that component.

For example

export default async function Page({ params }: { params: { room_id: string } }) {
    const checklistItems: ChecklistItem[] = await fetchChecklistInfo(params.room_id);

    return (
        <div className="relative inset-y-8">
            <div className="flex justify-center">
                <ScrollClientComponent checklist={checklistItems) *or more props />
            </div>
        </div>
    )
}


export default ScrollClientComponent (checklistItems) {
return (
       <ScrollArea className="h-[400px] w-[350px] rounded-md border p-4 shadow-xl">
              <ChecklistForm checklistItems={checklistItems} />
        </ScrollArea>
***Button can go here
)
}
If there is simply no way for me to do it with a server component then that's fair enough
It makes sense to me that a client child component wouldn't be able to send data to a server component. But what doesn't make sense to me is that I can't send a function to a client comp. I should really be able to send the child client comp a delegate of the onClick function in the submit button allowing me to send the data within the child comp
Sloth bear
You can put that button inside a separate component by itself and import it inside the server components. Then send that client button component props?
Or the other way round get the onClick function out of the button into the ChecklistForm
I know this would be resolved really easily if I just made the whole thing a client comp but I don't see why I should have to
Server components wont even let me make a react reference to the button and pass it to ChecklisForm, I just don't get it
American BobtailOP
@Sloth bear I've found a solution, thank you for your time and effort ❤️
Sloth bear
nice! can you share the solution that was found
^^
@Sloth bear nice! can you share the solution that was found
American BobtailOP
My solution was to wrap the scroll area and button in a context provider. This way a client component encompasses both the scroll area and button but it also holds state. The ChecklistForm and button can then set the state in the context provider with useContext. Since the scroll area is passed to the context provider from the Page (which is server side rendered) it remains a server component
Answer
American BobtailOP
For example
export default function Page() {
    return(
        <SomeContextProvider> {// this is a client component}
                <ServerComp /> {// this is rendered on the server despite being wrapped by a client component}
                <AnotherServerComp />{// so is this}
        </SomeContextProvider>
    )
}
Sloth bear
wow nice work!