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.
You are directly updating the notedata state when you filter. You need to filter the last state existing notedata