I'm new to learning react and have been having problems getting the array to filter using the .filter() method. I'm trying to create a grocery list and I keep getting the error message "Cannot read properties of null (reading 'filter')" Can someone please assist me on getting this work? Here is the code that I have.
import Header from './Header';
import SearchItem from './SearchItem';
import AddItem from './AddItem';
import Content from './Content';
import Footer from './Footer';
import { useState, useEffect } from 'react';
function App() {
const [items, setItems] = useState(JSON.parse(localStorage.getItem('shoppinglist')));
const [newItem, setNewItem] = useState('')
const [search, setSearch] = useState('')
console.log('before useEffect')
//useEffect looks to it's dependency and if the dependency changes then it will run the anonymous function
useEffect(() => {
console.log('inside useEffect')
},[items])
const setAndSaveItems = (newItems) => {
setItems(newItems);
localStorage.setItem('shoppinglist', JSON.stringify(newItems));
}
console.log('after useEffect')
const addItem = (item) => {
const id = items.length ? items[items.length - 1].id 1 : 1;
const myNewItem = { id, checked: false, item };
const listItems = [...items, myNewItem];
setAndSaveItems(listItems);
}
const handleCheck = (id) => {
const listItems = items.map((item) => item.id === id ? { ...item, checked: !item.checked } : item);
setAndSaveItems(listItems);
}
const handleDelete = (id) => {
const listItems = items.filter((item) => item.id !== id);
setAndSaveItems(listItems);
}
const handleSubmit = (e) => {
e.preventDefault();
if (!newItem) return;
addItem(newItem);
setNewItem('');
}
return (
<div className="App">
<Header title="Grocery List" />
<AddItem
newItem={newItem}
setNewItem={setNewItem}
handleSubmit={handleSubmit}
/>
<SearchItem
search={search}
setSearch={setSearch}
/>
<Content
items={items.filter(item => ((item.item).toLowerCase()).includes(search.toLowerCase()))}
handleCheck={handleCheck}
handleDelete={handleDelete}
/>
<Footer length={items.length} />
</div>
);
}
export default App;
CodePudding user response:
Few pointers that could help
initilize the items in an useEffect, it will make it easy to fetch data a api later
const [items, setItems] = useState([]);
useEffect(() => {
try {
const items = JSON.parse(localStorage.getItem('shoppinglist'))
setItems(items)
} catch(error) {
}
}, [])
// put a check on the filter, map funciton on items
const handleDelete = (id) => {
const listItems = items?.filter((item) => item.id !== id);
if (listItems) {
setAndSaveItems(listItems);
}
}
Id generated will clash and cause bugs
const id = items.length ? items[items.length - 1].id 1 : 1;
if the person deletes on item and adds another the new item will have the same id as the last one
- item { id: 1}
- item { id: 2}
- item { id: 3}
after deleting id 2, when you add new items it will have id 3 and will cause bugs with select
either use a id that is a timestamp or check for unique ids
- Save the items in local storage on submit, as calls get/set items to localstorage can lead to performace issues in the UI
Checkout the new docs on working with arrays
Hope it helps
CodePudding user response:
I feel that you're mentioning about this code excerpt:
items.filter((item) => item.id !== id);
can you please check if the items array is null or not. Only if items is null, filtering wouldn't be applicable and you will receive such error messages
can you log items before deletion?