首页 > 解决方案 > 类型错误:无法将 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)=>{

标签: reactjs

解决方案


问题是您无法从未定义的对象创建键数组。

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: {} }
});

推荐阅读