Next.js Discord

Discord Forum

How to deal with handlers not being able to be passed to Client Component props?

Unanswered
Yellowfin tuna posted this in #help-forum
Open in Discord
Yellowfin tunaOP
I'm trying to design a page (server component) that has a hook that creates an API call and two components (one SSR and one using client).

Then the first client component displays the values contained in fragment const, while the second component is a search bar that stores the value of the input into a state.

I want to pass the value of the state (searchQuerry) to the page containing the api call to edit (as the variable searchPrompt), but unfortunately, I am getting the following error:

Error: Event handlers cannot be passed to Client Component props. <... onSearchChange={function}> If you need interactivity, consider converting part of this to a Client Component.




Here is my code:

Search Input:

"use client"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react" import qs from 'query-string'; interface SearchParamsProps { onSearchChange: Function; } const SearchParams:React.FC<SearchParamsProps> = ({ onSearchChange, }) => { const [searchQuerry, setSearchQuerry] = useState<string>(""); const router = useRouter(); const handleSearch = () => { const query = { fragment: searchQuerry, }; const url = qs.stringifyUrl({ url: "/search", query: query }); router.push(url); alert(url); } return ( <div className="flex flex-row gap-2 justify-center mx-5 md:mx-0"> <input type = "search" className="w-2/3 sm:w-1/2 border-2 rounded-sm px-2 py-2 shadow-md [&::-webkit-search-cancel-button]:grayscale" placeholder={"Search for " + wantQuotes + " by " + searchCategory + "..."} value = {searchQuerry} onChange = {(e) => {setSearchQuerry(e.target.value)}} /> <button onClick={onSearchChange(searchQuerry)} className="flex flex-row gap-1 items-center py-2 px-4 dark:bg-indigo-600 bg-indigo-500 hover:bg-indigo-600 dark:hover:bg-indigo-700 text-white rounded-sm shadow-md"> <IoSearchSharp /> Search </button> </div> ) } export default SearchParams;

7 Replies

Yellowfin tunaOP
Here is the Search component code:
Main Page:
import PageContent from '@/components/PageContent'; import SearchParams from '@/components/SearchParams'; import getFragmentsByTitle from '@/actions/getFragmentsbyTitle'; interface SearchProps { searchPrompt: string; }; export const revalidate = 0; const Search:React.FC<SearchProps> = async ({ searchPrompt, }) => { //var searchPrompt = ""; For testing the search functionalty const handleSearchChange = (prompt:string) => { searchPrompt = prompt; } const fragment = await getFragmentsByTitle(searchPrompt); return ( <div className='z-20 pb-10'> <SearchParams onSearchChange = {() => handleSearchChange}/> <PageContent fragment={fragment}/> </div> ) } export default Search;
@Yellowfin tuna I'm trying to design a page (server component) that has a hook that creates an API call and two components (one SSR and one using client). Then the first client component displays the values contained in fragment const, while the second component is a search bar that stores the value of the input into a state. I want to pass the value of the state (searchQuerry) to the page containing the api call to edit (as the variable searchPrompt), but unfortunately, I am getting the following error: Error: Event handlers cannot be passed to Client Component props. <... onSearchChange={function}> If you need interactivity, consider converting part of this to a Client Component. Here is my code: Search Input: `"use client"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react" import qs from 'query-string'; interface SearchParamsProps { onSearchChange: Function; } const SearchParams:React.FC<SearchParamsProps> = ({ onSearchChange, }) => { const [searchQuerry, setSearchQuerry] = useState<string>(""); const router = useRouter(); const handleSearch = () => { const query = { fragment: searchQuerry, }; const url = qs.stringifyUrl({ url: "/search", query: query }); router.push(url); alert(url); } return ( <div className="flex flex-row gap-2 justify-center mx-5 md:mx-0"> <input type = "search" className="w-2/3 sm:w-1/2 border-2 rounded-sm px-2 py-2 shadow-md [&::-webkit-search-cancel-button]:grayscale" placeholder={"Search for " + wantQuotes + " by " + searchCategory + "..."} value = {searchQuerry} onChange = {(e) => {setSearchQuerry(e.target.value)}} /> <button onClick={onSearchChange(searchQuerry)} className="flex flex-row gap-1 items-center py-2 px-4 dark:bg-indigo-600 bg-indigo-500 hover:bg-indigo-600 dark:hover:bg-indigo-700 text-white rounded-sm shadow-md"> <IoSearchSharp /> Search </button> </div> ) } export default SearchParams;`
you can do it with only html form
import PageContent from "@/components/PageContent";
import SearchParams from "@/components/SearchParams";
import getFragmentsByTitle from "@/actions/getFragmentsbyTitle";
interface SearchProps {
  searchPrompt: string;
}
export const revalidate = 0;
const Search: React.FC<SearchProps> = async ({ searchParams }) => {
  const fragment = await getFragmentsByTitle(searchParams);
  return (
    <div className="z-20 pb-10">
      <form className="flex flex-row gap-2 justify-center mx-5 md:mx-0">
        <input
          type="search"
          name="fragment"
          className="w-2/3 sm:w-1/2 border-2 rounded-sm px-2  py-2 shadow-md [&::-webkit-search-cancel-button]:grayscale"
          placeholder={
            "Search for " + wantQuotes + " by " + searchCategory + "..."
          }
        />
        <button className="flex flex-row gap-1 items-center py-2 px-4 dark:bg-indigo-600 bg-indigo-500 hover:bg-indigo-600 dark:hover:bg-indigo-700 text-white rounded-sm shadow-md">
          <IoSearchSharp />
          Search
        </button>
      </form>
      <PageContent fragment={fragment} />
    </div>
  );
};
export default Search;
Yellowfin tunaOP
Thanks a lot for your answer! So this way searchParams will be equal to what I type into the input? The reality is that I now only want to search based on what the user types in the input, but I also have some buttons that act as filters, that's why I wanted to be able to use the states from the SearchParams component
Yellowfin tunaOP
I was trying to use the url to get the searchParams but sadly the usePathname from react-navigation also requires a client component
@Yellowfin tuna I was trying to use the url to get the searchParams but sadly the usePathname from react-navigation also requires a client component
the server component will get the searchParams in their props, so you don't need to pass onSearchChange to the client
Yellowfin tunaOP
Thanks a lot, I managed to fix it by changing my api calls to not require next-headers. I will keep it the way I have it but many thanks!