0

I am trying to create my first search bar in React.js. I am trying to implement search functionality with filter method. I faced a problem with filter method, which gives an error like "filter is not defined". I am stuck on it for 2 days, I have looked several tutorials and endless youtube videos. This is the simpliest approach, I guess. Any help will be appreciated.

import React, { useState, useEffect } from "react";
import Recipe from "./Recipe";
import "./styles.css";

export default function RecipeList() {
  const apiURL = "https://www.themealdb.com/api/json/v1/1/search.php?f=c";
  const [myRecipes, setRecipes] = useState("");
  const [search, setSearch] = useState("");

  // fetch recipe from API
  function fetchRecipes() {
    fetch(apiURL)
      .then(response => response.json())
      .then(data => setRecipes(data.meals))
      .catch(console.log("Error"));
  }

  function onDeleteHandler(index) {
    setRecipes(
      myRecipes.filter((element, filterIndex) => index !== filterIndex)
    );
  }
  useEffect(() => {
    fetchRecipes();
  }, []);

 const filterRecipes = myRecipe.meal.filter( element => {
return element.name.toLowerCase().includes(search.toLocaleLowerCase())
 })
{/* filter method above doesn't work */}

  return (
    <div>
       <label>
          <div className="input-group mb-3 cb-search">
            <input
              type="text"
              className="form-control"
              placeholder="Search for recipes..."
              aria-label="Recipient's username"
              aria-describedby="button-addon2"
              onChange = {e => setSearch (e.target.value)}
            />
            <div className="input-group-append">
              <button
                className="btn btn-outline-secondary"
                type="button"
                id="button-addon2"
              >
                Search
              </button>
            </div>
          </div>
        </label>
      <div>
        <button
          className="btn btn-info cb-button fetch-button"
          onClick={fetchRecipes}
        >
          Fetch Recipe
        </button>
        <br />
        {filterRecipes.map((element, index) => (
        <Recipe    
          key={index}
          index = {index}
          onDelete={onDeleteHandler}
          {...element}
          name = {element.strMeal} 
        />
      ))} 
      {/** name of child component */}
      {/** strMeal is the name of Recipe in API object */}
      </div>
    </div>
  );
}

link for code codesandbox

2
  • At least so you can get past your not defined problem, myRecipe.meal looks like a typo and you wanted myRecipes.meal. After that, your default state is an empty string which doesn't have filter on it. A better initial state may be an empty array [] Commented Apr 27, 2020 at 23:53
  • @SeamusR I made correction, now code works, but API gives an error Commented Apr 28, 2020 at 0:28

2 Answers 2

1

I made some changes on your code updated code

  1. const [myRecipes, setRecipes] = useState([]);

You should declare myRecipes as an array if u intended to use map function.

  1. const filterRecipes = myRecipe.meal.filter( element => { return element.name.toLowerCase().includes(search.toLocaleLowerCase()) })

You have the wrong variable passing through, it should be myRecipes

filterRecipes.map((element, index) => (
       <Recipe    
         key={index}
          index = {index}
          onDelete={onDeleteHandler}
          {...element}
          name = {element.strMeal} 
        />

3. You should check whether your filterRecipes is not undefined before you use map function.

  1. Lastly, your fetch API return error which unable to setRecipes.
Sign up to request clarification or add additional context in comments.

1 Comment

I agree with you. I made changes in filter function ``codeconst filterRecipes = myRecipes.filter(element => { return element.strMeal.toLowerCase().includes(search.toLocaleLowerCase()); }); and in map function as well, but as you said, API still return errror
1

I could not resolve you task completely because of low count of information according the task, but, i think, my answer will be useful for you.

So, tthe first thing I would like to draw attention to is a initial state in the parameter of useState function. In this task it sould be as:

const [myRecipes, setRecipes] = useState({meals: []});

Because, before fetching data, React has a time to run the code, and, when it come to line 32, it see what in the myRecipes (myRecipes, not a myRecipe. Please, pay attention when you write the code) a string except an array.

And in the line 32 i recommend you to add something checking of have you resolved request of data like:

const filterRecipes = myRecipes.meals.length 
 ?  myRecipes.meals.filter(element => {
    return element.name.toLowerCase().includes(search.toLocaleLowerCase());
  });
 : []

And look in the data which you receive, because, i think, there are no elements with propName like name (element.name).

I think, i could help you as possible. If you have any questions, ask in comments. Will answer you as soon as possible. Good luck

1 Comment

you couldn't resolve it, because it was my bad. I did as you said with some corrections, and it worked. thank you so much

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.