Create a filtering function in react

Create a filtering function in react


0

I want to create a filtering function that trigger when receiving a input value event in react useState but i do not see is doing anything when I start typing in. This is my Search component

export function Search({categories, onSearch}){
    const [searchText, setSearchText] = useState('');

    const filterCategories = () => {
        const filteredCategories = categories.filter(category =>
          category.name.toLowerCase().includes(searchText.toLowerCase())
        );
        onSearch(filteredCategories);
      };
    
      const handleInputChange = event => {
        setSearchText(event.target.value);
        filterCategories();
      };


    return (
        <div className="flex items-center"> 
        <form className='flex space-x-1' >
         <input 
                     type="text"
                     className="block w-full px-4 py-2 text-purple-700 bg-white border rounded-full focus:border-purple-400 focus:ring-purple-300 focus:outline-none focus:ring focus:ring-opacity-40"
                     placeholder="Search..."  
                     value={searchText}
                     onChange={handleInputChange}
                    />
       
        </form>
        </div>
    )
}

Then is being used here

const Layout = ({ categories, children }) => {
  const [filteredCategories, setFilteredCategories] = useState(categories);

  const handleSearch = (filteredCategories) => {
    setFilteredCategories(filteredCategories);
  };

  return (
    <div>
      {/* ... */}
      <Search categories={categories} onSearch={handleSearch} />
      {/* ... */}
      {children}
    </div>
  );
};

export default Layout;

and That goes into the Home component

export default function Home({ posts, categories }) {

  return (
    <Layout categories={categories}>
      <div className="mt-20">
        <main className="flex flex-col justify-center items-center h-screen pt-10 pb-30">
          {/* Render posts */}
        </main>
      </div>
    </Layout>
  );
}

Is there anything I should do to make this work?

Share

3 Answers
3

Reset to default


0

In the Layout component you are passing categories value to your Search component, you probably meant to pass filteredCategories

const Layout = ({ categories, children }) => {
  const [filteredCategories, setFilteredCategories] = useState(categories);

  const handleSearch = (filteredCategories) => {
    setFilteredCategories(filteredCategories);
  };

  return (
    <div>
      {/* ... */}
      <Search
        categories={filteredCategories} // here
        onSearch={handleSearch}
      />
      {/* ... */}
      {children}
    </div>
  );
};

export default Layout;

(filteredCategories was unused which made you feel that nothings was happening)

Share


0

Your code seems correct. Ensure categories have valid data with name property. To debug, add console.log in handleInputChange and filterCategories to see if they’re triggered and check the console for issues. If the input change and filtering events are working, it might be a styling or UI issue. Look at my code bellow i updated

import React, { useState } from 'react';

export function Search({ categories, onSearch }) {
  const [searchText, setSearchText] = useState('');

  const filterCategories = () => {
    const filteredCategories = categories.filter(category =>
      category.name.toLowerCase().includes(searchText.toLowerCase())
    );
    onSearch(filteredCategories);
  };

  const handleInputChange = event => {
    const searchText = event.target.value;
    console.log("Input Change:", searchText);
    setSearchText(searchText);
    filterCategories();
  };

  return (
    <div className="flex items-center">
      <form className="flex space-x-1">
        <input
          type="text"
          className="block w-full px-4 py-2 text-purple-700 bg-white border rounded-full focus:border-purple-400 focus:ring-purple-300 focus:outline-none focus:ring focus:ring-opacity-40"
          placeholder="Search..."
          value={searchText}
          onChange={handleInputChange}
        />
      </form>
    </div>
  );
}

Share


0

your handleSearch function passed as props onSearch to Search component expects an arg filteredCategories to set it to its state filteredCategories.

Now you are calling it each time you type in the input:

onChange={handleInputChange}

what it does ?

const filteredCategories = categories.filter(category => 
category.name.toLowerCase().includes(searchText.toLowerCase()));
onSearch(filteredCategories);

so you filtter based on searchText then you call onSearch passing the result of your filter i.e filteredCategories, however, this is not the correct approach since searchText won’t be updated immediately but when the component rerenders (so you are a step late), therefore, you have to filter based on the input value not the state, in fact, with your implementation, you don’t even need the searchText state at all:

const handleInputChange = event => {
   filterCategories(event.target.value);
};

// ...

const filterCategories = (value) => {
const filteredCategories = categories.filter(category => 
category.name.toLowerCase().includes(value.toLowerCase()));
onSearch(filterCategories)
}

Now you have the correct logic to update filteredCategories state in the parent component (Layout) and you should see the expected filtred data logged each time you type in the child component input causing the layout component to rerender:

const Layout = ({ categories, children }) => {
  const [filteredCategories, setFilteredCategories] = useState(categories);
  console.log("function called: ", filteredCategories);
  // ...
}

Share



Not the answer you're looking for? Browse other questions tagged

or ask your own question.

Leave a Reply

Your email address will not be published. Required fields are marked *