So, i am trying to build search page where i search for an item from an array of items(objects with multiple properties) and so the approach i used to match currently searched item with the one in the list was to use the .include()
to get the matching names and then accordingly populate the array.
Now, the problem is that every time the loop runs, it matches the name and pushes the element into the searched array without any filtering , resulting in duplicate elements being filled in. I have used .filter()
to remove duplicity but it is not reflecting in the state.
useEffect(()=>{
setSearchedArray([]);
allItems.forEach(item => {
if(item.name.toUpperCase().includes(searchText.toUpperCase())){
// Also check whether the searched array already has that element or not.
setSearchedArray([...searchedArray, item])
console.log('searchedArray before filtering : ',searchedArray)
var pp = searchedArray.filter( (ele, ind) => ind === searchedArray.findIndex( elem => elem.id === ele.id));
console.log(pp);
setSearchedArray(pp);
}
});
},[searchText, setSearchText]);
This use effect only implements when the user starts typing into the input box.
The console.log(pp)
is giving the correct output e.i., the filtered elements array but when I set it in setSearchedArray(pp)
it is not reflecting the change into searchedArray
state.
CodePudding user response:
I'm not too sure on reactjs specific code but I can help you with your loop logic.
Your code has several problems:
- For loops it's best to use a
while loop
orfor loop
, theforEach loop
has a lot of overhead ( bad for performance ). - You're duplicating work by doing
searchText.toUpperCase()
on each loop. - Overly complicated filtering. Keep it simple. Simplify the logic by checking for things you don't need first.
- You pass in
setSearchText
but are usingsetSearchedArray
, not sure if that is something that is affecting your code or just something that is reactjs specific.
useEffect(()=>{
const searchString = searchText.trim().toUpperCase();
const searchItems = [];
const searchKeys = [];
for ( const item of allItems ) {
const itemName = item.name.trim().toUpperCase();
if ( searchKeys.includes( itemName ) ) continue;
if ( itemName.includes( searchString ) == false ) continue;
searchKeys.push( itemName );
searchItems.push( item );
}
setSearchedArray( searchItems );
},[searchText, setSearchedArray]);