Search code examples
javascriptreactjsreact-hookscomponents

facing problem in state after filtering in my create-react app


I am new to react and I am making Note-keeping application using react and firebase. Data is properly store and retrieve from firebase and rendering properly on UI.

I have an Input filed on Navbar to searching for a note.

problem i am facing:

when i search for particular note it got filtered, but when i do empty my search filed only filtered item is visible.

Its due to improper state management-(if i am not wrong), but i don't how to manage it properly.

This is my App component from where i am passing my Notes which is fetch from firebase to the Navbar component.

import './App.css';
import NavBar from './components/Navbar/NavBar';
import Header from './components/Header/Header';
import Card from './components/Card/Card';
import { useEffect, useState } from 'react';

function App() {
  const [notedata, setNoteData] = useState([]);

  // fetch data from firebase.
  let autoFetch = async () => {
    const response = await fetch('https://notes-keeper-react-default-rtdb.firebaseio.com/notes.json');
    const data = await response.json();

    let notesArr = [];
    Object.keys(data).map((key) => {
      notesArr.push(data[key]);
    });
    setNoteData(notesArr);
  };

  useEffect(() => {
    autoFetch();
  }, []);

  console.log('Data in App comp: ', notedata);
  return (
    <div className='App'>
      <NavBar noteData={notedata} setNoteData={setNoteData} />
      <Header autoFetch={autoFetch} />
      <Card notes={notedata} />
    </div>
  );
}

export default App;

And this is my Navbar component where i am filtering:

import { useState, useEffect } from 'react';
import classes from './NavBar.module.css';

export default function NavBar(props) {
  const [filterSearch, setFilterSearch] = useState('');

  const myNotes = [...props.noteData];

  const filterHandler = (event) => {
    let searchItem = event.target.value.toLowerCase();

    setFilterSearch(searchItem);

    console.log('searching for: ', searchItem);

    // if (searchItem.length > 0) {
    //   const filterNote = props.noteData.filter((note) => note.title.toLowerCase().includes(filterSearch));
    //   props.setNoteData(filterNote);
    // } else {
    //   props.setNoteData(props.noteData);
    // }

    const filterNote = myNotes.filter((note) => note.title.toLowerCase().includes(searchItem));

    console.log('MyNotes(copied): ', myNotes, ' filterNote: ', filterNote);

    props.setNoteData(searchItem.length > 0 ? filterNote : props.noteData);
  };

  // useEffect(() => {
  //   console.log('inside filter useEffect');
  //   const filterNote = filterSearch
  //     ? props.noteData.filter((note) => note.title.toLowerCase().includes(filterSearch.toLowerCase()))
  //     : props.noteData;
  //   props.setNoteData(filterNote);
  // }, [filterSearch]);

  return (
    <div className='container'>
      <nav>
        <div className={classes['nav-heading']}>
          <h1>Notes</h1>
        </div>
        <div className={classes['nav-search']}>
          <div className={classes['nav-controls']}>
            <input
              type='text'
              name='search'
              id='search'
              placeholder='Search for Title'
              value={filterSearch}
              onChange={filterHandler}
            />
          </div>
        </div>
      </nav>
    </div>
  );
}

I also tried these Commented codes.

This is my console when i am searching: console during search

This is my console when i do empty my search field: console after empty search field

If you carefully see the states on console, you will see the problem.


Solution

  • You are directly updating the notedata state when you filter. You need to filter the last state existing notedata