reactjs - 类型错误:无法将 undefined 或 null 转换为对象
问题描述
我正在尝试从我的 app.js 组件中的本地存储中获取数据,并使用上下文 api 挂钩将其传递给其他组件。使用该数据我正在显示我的购物车,但是当我重新加载我的购物车页面时,我的购物车变空了。我使用 Object.keys() 方法将我的对象键转换为数组。
我的 App.js 代码
import {React ,useState ,useEffect} from 'react'
import {BrowserRouter as Router ,Route,Switch} from 'react-router-dom';
import Nav from './components/Nav';
import Home from './components/Home';
import Products from './components/Products';
import Cart from './components/Cart';
import SingleItem from './components/SingleItem';
import {CartContext} from './components/CartContext';
import userEvent from '@testing-library/user-event';
import {PaymentForm} from './components/PaymentForm'
function App() {
const [cart,setCart]=useState({});
useEffect(() => {
const cart=window.localStorage.getItem('cart');
setNav(false);
console.log(showNav);
console.log(JSON.parse(cart));
}, [])
useEffect(() => {
window.localStorage.setItem('cart',JSON.stringify(cart))
}, [cart]);
return (
<>
<Router>
<CartContext.Provider value={{cart,setCart}}>
<Nav/>
<Switch>
<Route path="/" component={Home} exact></Route>
<Route path="/products" exact component={Products}></Route>
<Route path="/products/:id" component={SingleItem}></Route>
<Route path="/cart" component={Cart} exact></Route>
<Route path="/PaymentForm" component={PaymentForm} exact></Route>
</Switch>
</CartContext.Provider>
</Router>
</>
)
}
export default App;
我的 cart.js 代码
import {useContext, useEffect ,useState} from 'react'
import { findDOMNode } from 'react-dom';
import {CartContext} from './CartContext';
import {Link} from 'react-router-dom';
import contents from './contents';
import './styles.css';
import PaymentForm from './PaymentForm'
function Cart() {
const [products,setproducts]= useState([]);
let total=0;
const {cart,setCart}= useContext(CartContext)
console.log(cart.totalItems);
console.log(cart);
useEffect(() => {
if(cart.totalItems===0)
{
console.log("empty");
return (<img className="mx-auto w-3/4 mt-12" src="/images/emptycart.jpg" alt="" />)
}
else
{
console.log(Object.keys(cart.items));
(Object.keys(cart.items)).map((m,i)=>{
contents.map((content,j)=>{
if(content._id===m )
{
console.log("naman",i,j);
if(products){
products.push(content);
}
console.log(content.name);
}
})
})
}
}, [cart]);
console.log(contents);
const getquantity=(product)=>{
return(cart.items[product._id])
}
const increment=(product)=>{
const oldqty=cart.items[product._id];
const _cart={...cart};
_cart.items[product._id]=oldqty+1;
_cart.totalItems++;
setCart(_cart);
}
const decrement=(product)=>{
const oldqty=cart.items[product._id];
const _cart={...cart};
if(oldqty===1)
{
return
}
_cart.items[product._id]=oldqty-1;
_cart.totalItems--;
setCart(_cart);
}
const getSum=(product)=>{
const p=product.price
const sum=p*getquantity(product)
let t=0
sum?total=total+sum:t=1;
return sum;
}
const Ondelete=(productid)=>{
const _cart={...cart};
const oldqty=_cart.items[productid];
delete( _cart.items[productid]);
console.log(cart.items);
_cart.totalItems=_cart.totalItems-oldqty;
alert("Item deleted from Cart")
setCart(_cart);
}
const orderNow=()=>{
< paymentForm/>
}
return (
cart.totalItems?
<div>
<div className="container mb-10 pr-20 ">
<h1 className="font-bold my-5 mx-40 font">Cart Items</h1>
<ul>
{
contents.map((content,i)=>{
var product=content;
if(cart.items[product._id])
{
return(<li className="mb-12" key={i}>
<div className="maincart ">
<div className=" maincontent ">
<img className="maincartimg ml-5 "src={content.img} alt="" />
<span className="ml-5 font-bold font ">{content.name}</span>
</div>
<div className="cartcontainer">
<button onClick={()=>decrement(product)} className="bg-yellow-500 py-2 px-4 rounded-full addbtn leading-none">-</button>
<span className="font-bold px-4">{getquantity(product)?getquantity(product):0}</span>
<button onClick={()=>increment(product)} className="bg-yellow-500 py-2 px-4 rounded-full addbtn leading-none">+</button>
</div>
<div className="cartbtn">
<span className="font m-10">{getquantity(product)?getSum(product):0}</span>
<button onClick={()=>Ondelete(product._id)} className="bg-red-500 px-4 py-2 rounded-full addbtn leading-none"><i class="fas fa-trash mr-2"></i>Delete</button>
</div>
</div>
{}
</li>)}
})}
</ul>
<hr className="my-6"/>
<div className="order">
<div className="text-right pr-20"> <span className="font-bold"> <b>TOTAL PRICE:</b>{total}</span></div>
<div className="text-right mt-6 pr-20 " ><Link to="/PaymentForm" className="bg-yellow-500 px-4 py-2 rounded-full">Order Now</Link></div>
</div>
</div>
</div>
:
<div className="emptycart">
<h1 className=" mt-3 text-4xl font-bold"> Empty Cart</h1>
<img className="mx-auto mb-5 emptycartimg w-1/2 mt-5" src="/images/emptycart.jpg" alt="" />
</div>
)
}
export default Cart
重新加载购物车页面时出错
TypeError: Cannot convert undefined or null to object
(anonymous function)
C:/Users/lenovo/Desktop/react cart/my-cart/src/components/Cart.js:23
20 | }
21 | else
22 | {
> 23 | console.log(Object.keys(cart.items));
| ^ 24 |
25 |
26 | (Object.keys(cart.items)).map((m,i)=>{
解决方案
问题是您无法从未定义的对象创建键数组。
Object.keys(cart.items))
const cart = {};
Object.keys(cart.items);
cart
您应该在包含items
属性的提供程序中提供有效的初始状态。
function App() {
const [cart, setCart] = useState({ items: {} });
...
return (
<Router>
<CartContext.Provider value={{ cart, setCart }}>
...
const cart = { items: {} };
console.log(Object.keys(cart.items));
更新
cart
状态持久性不起作用的原因是您没有从 localStorage 初始化您的状态。第二个useEffect
是擦除任何持久的购物车数据。
function App() {
const [cart, setCart] = useState({}); // <-- (1) initially empty
useEffect(() => {
const cart = window.localStorage.getItem('cart');
setNav(false);
console.log(showNav);
console.log(JSON.parse(cart));
}, []);
useEffect(() => {
window.localStorage.setItem( // <-- (2) writes initial empty state
'cart',
JSON.stringify(cart),
);
}, [cart]);
您应该cart
从 localStorage 初始化本地状态,如果 localStorage 为空,则返回有效的初始状态。
const [cart, setCart] = useState(() => {
return JSON.parse(window.localStorage.getItem("cart")) || { items: {} }
});
推荐阅读
- java - 更改 PreferenceFragment 的 StatusBar 颜色
- python - Argparse 错误:python2.x 上的参数太少
- maven - 如何在maven中锁定依赖版本?
- java - 关于 Rollbak 的领域事件
- python - 产生稀疏成对距离矩阵python避免内存错误
- flutter - 在主页颤动中调用函数或方法
- android - 我需要在 kotlin 中将用户输入从一个活动传递到另一个活动
- javascript - 在 1900 年之前在 javascript 中解析日期会增加 14 秒
- python - 如何正确设置数据集以训练 Keras 模型
- oracle - 如何将从oracle apex 20.1多选项返回的字符串值转换为逗号分隔的数字数组