React购物清单开发报错:Cannot read properties of null (reading 'filter')求助
解决"Cannot read properties of null (reading 'filter')"错误
错误原因
应用首次加载时,localStorage.getItem('shoppinglist')返回null(未保存过数据),经JSON.parse转换后,items的初始状态为null。而null不是数组,无法调用filter方法,因此在Content组件的items={items.filter(...)}行触发报错。
解决方案
给useState的初始值添加空数组兜底,确保items始终为数组类型,让所有数组方法能正常执行。
修改初始状态代码:
const [items, setItems] = useState(JSON.parse(localStorage.getItem('shoppinglist')) || []);
逻辑说明
- 当
localStorage存有数据时,JSON.parse返回保存的数组,|| []不生效; - 当
localStorage无数据时,JSON.parse(null)返回null,|| []将初始值替换为空数组,避免null引发的方法调用错误。
修改后的完整代码
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() { // 添加空数组兜底,确保items始终为数组 const [items, setItems] = useState(JSON.parse(localStorage.getItem('shoppinglist')) || []); const [newItem, setNewItem] = useState('') const [search, setSearch] = useState('') console.log('before useEffect') 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;
内容的提问来源于stack exchange,提问作者ssmith416
相关产品推荐
相关产品推荐

