React Element getting rendered even after change

Viewed 88

I am new to React but I am having a problem with this simple app

I am trying to add a search functionality but whenever I search the search element results are gets rendered

and when I remove everything from the search box all elements display as intended

But the previously rendered search elements are also there with all the list

Logic Example :

Like I searched for A from [A.B.C] and render A then when I remove A from the search box it renders all A,B,C but also previous render A also stays in end so the complete rendered list goes like A.B.C.A

I need a way to remove this searched A or just one time render these searched element

I need to remove these Rendered elements anyhow or hide them or anyhow only display only all elements

Here is my App.js

import React , {useState , useEffect} from 'react'
import RecipieList from "./RecipieList";
import RecipieEdit from './RecipieEdit';
import { v4 as uuidv4 } from 'uuid';
import Search from './Search';
import "../css/app.css"

export const RecipieContext = React.createContext()

const LOCAL_STORAGE_KEY = "cookingwithreact.app.recipies"

function App() {
  const storedRecipies = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY)) ;
  const [selectedRecipieId , setSelectedRecipie] = useState("")
  const [search , setSearch] = useState(undefined)

  if(storedRecipies.length < 1){
    constRecipies.forEach((constRecipie)=>{
      storedRecipies.push(constRecipie)
    })
  }

  const [recipies , setRecipies] = useState(storedRecipies)
  const selectedRecipie = recipies.find(recipie => recipie.id === selectedRecipieId)
  
  useEffect(()=>{
    const recipeJSON = localStorage.getItem(LOCAL_STORAGE_KEY)
    if(recipeJSON !=null) setRecipies(JSON.parse(recipeJSON))
  },[])

  useEffect(()=>{
    localStorage.setItem(LOCAL_STORAGE_KEY , JSON.stringify([...recipies]))
  },[recipies])
  
  const recipieContextValue = {
    handleRecipieAdd,
    handleRecipieSelect,
    handleRecipieChange,
    handleRecipieDelete
  }
  
  function handleRecipieChange(id,editedRecipie){
    const newRecipies = [...recipies]
    const index = newRecipies.findIndex(e => e.id === id)
    newRecipies[index] = editedRecipie
    setRecipies(newRecipies)
  }

  function handleRecipieSelect(id){
    setSelectedRecipie(id)
  }

  function handleRecipieAdd(){
    let newRecipie = {
      id:uuidv4(),
      name:"",
      cookTime:"",
      servings : "",
      instructions : "",
      items:[
        {
          id:uuidv4(),
          name:"",
          amount:""
        }
      ]
    }
    handleRecipieSelect(newRecipie.id)
    setRecipies([...recipies,newRecipie])
  }

  function handleRecipieDelete (id){
    if(selectedRecipieId !=null && selectedRecipieId === id){
      setSelectedRecipie(undefined)
    }
    setRecipies(recipies.filter(recipie => recipie.id !== id))
  }

  return (
      <RecipieContext.Provider value={recipieContextValue}>
        <Search recipies={recipies} recipieContextValue={recipieContextValue} setSearch = {setSearch}></Search>
        {!search && <RecipieList recipies={recipies} ></RecipieList>}
        {selectedRecipie && <RecipieEdit recipie = {selectedRecipie}/>}
      </RecipieContext.Provider>  )
}

export let constRecipies = [
  {
    id : 1,
    name:"Poha",
    cookTime:"00:10",
    servings : "2",
    instructions : "1. Take Poha \n2. Make Poha \n3. Eat Poha",
    items : [
      {
        id:1,
        name:"Poha",
        amount:"1 Packet"
      },
      {
        id:2,
        name:"Namkeen",
        amount:"2 Packet"
      },
      {
        id:3,
        name:"Spices",
        amount:"3 Packet"
      }
    ]
  },
  {
    id : 2,
    name:"Maggi",
    cookTime:"00:20",
    servings : "3",
    instructions : " 1. Take Maggi \n 2. Make Maggi \n 3. Eat Maggi",
    items : [
      {
        id:1,
        name:"Maggi",
        amount:"1 Packet"
      },
      {
        id:2,
        name:"Veges",
        amount:"1 Packet"
      },
      {
        id:3,
        name:"Spices",
        amount:"1 Packet"
      }
    ]
  },
]

export default App;

and here is Search.js

import { render } from '@testing-library/react';
import React  from 'react';
import RecipieSearchList from './RecipieSearchList';
import RecipieList from './RecipieList'

export default function Search(props) {
    const {recipies , setSearch ,recipieContextValue} = props

    function handleSearch(searchedTerm){
        
        if(searchedTerm.length > 0){
            let foundedRecipies = recipies.filter(element => element.name.includes(searchedTerm));
            console.log(foundedRecipies)
            setSearch("defined")
            render(
                <RecipieSearchList recipieContextValue={recipieContextValue} recipies={foundedRecipies}/>
            )

        }
        else{
            console.log("Search is Empty")
            setSearch(undefined)
        }
    }

  return (
      <>
      <div className='search-container'>
          <input 
          onChange={(e)=>{handleSearch(e.target.value)}} 
          className='search-field' placeholder='Search' 
          type="text" id='search'/>
      </div>
      </>
  )
}

Here is the Github Link

1 Answers

So Guys i found a workaround of the problem that instead of rendering if I return it should work fine

The Probelm I was having is with logic

Here is the code I came up with is to check from the beginning if there is already available recipes or not

      recipes.filter((val)=>{
          if(search == ""){
              return val
          }
          else if(val.name.toLocaleLowerCase().includes(search.toLocaleLowerCase())){
              return val
          }
      }).map((recipe,key)=>{
          return <Recipe key={key} recipe={recipe}></Recipe>
      })
Related