开发者问题收集

ReactJs:TypeError:无法分配给对象“#<Object>”的只读属性“cartHandler”?

2021-05-17
3295

我正在尝试建立一个餐厅网站。我已经建好了一半。但我在某个地方卡住了。我遇到了错误。我无法在我的代码中找出问题所在。每当我尝试通过单击添加按钮添加新食物时,我都会收到 TypeError:无法分配给对象“#”的只读属性“cartHandler”?.. 我尝试在 cartHandler 对象中调试,但多次遇到相同的错误。有人可以检查一下吗?

这是我的 App.js 文件

import logo from './logo.svg';
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";
import './App.css';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css'
import Banner from './components/Banner/Banner';
import Header from './components/Header/Header';
import Foods from './components/Foods/Foods';
import Features from './components/Features/Features';
import Footer from './components/Footer/Footer';
// import SIgnUp from './components/SignUp/SIgnUp';
import NotFound from './components/NotFound/NotFound';

import FoodItemDetails from './components/FoodItemDetails/FoodItemDetails'
import { createContext, useContext, useState } from 'react';
import Login from './components/Login/Login';


export const userContext = createContext();

function App() {

  const [cart , setCart] = useState([]);
  const [orderId , setOrderId] = useState(null);
  
  const [deliveryDetails , setDeliveryDetails] = useState({
    todoor:null,road:null, flat:null, businessname:null, address: null
  });

  const [userEmail, setUserEmail] = useState(null);
  const deliveryDetailsHandler = (data) => {
      setDeliveryDetails(data)
  }
  const getUserEmail = (email) => {
    setUserEmail(email);
  }

  const clearCart =  () => {
    const orderedItems = cart.map(cartItem => {
      return {food_id : cartItem.id, quantity: cartItem.quantity}
    })

    const orderDetailsData = { userEmail , orderedItems,  deliveryDetails }
    fetch('https://red-onion-backend.herokuapp.com/submitorder' , {
        method : "POST",
        headers: {
            "Content-type" : "application/json"
        },
        body : JSON.stringify(orderDetailsData)
    })
    .then(res => res.json())
    .then(data=> setOrderId(data._id))
    console.log(orderId);

    setCart([])
  }

  const cartHandler = (data) => {
    const alreadyAdded = cart.find(crt => crt.id == data.id );
    const newCart = [...cart,data]
    setCart(newCart);
    if(alreadyAdded){
      const reamingCarts = cart.filter(crt => cart.id != data);
      setCart(reamingCarts);
    }else{
      const newCart = [...cart,data]
      setCart(newCart);
    }
   
  }

  const checkOutItemHandler = (productId, productQuantity) => {
    const newCart = cart.map(item => {
      if(item.id == productId){
          item.quantity = productQuantity;
      }
      return item;
    })

    const filteredCart = newCart.filter(item => item.quantity > 0)
    setCart(filteredCart)
  }
 




  const [logggedInUser, setLoggedInUser] = useState({});
  const [signOutUser, setSignOutUser] = useState({});
  return (
    <userContext.Provider value={([logggedInUser, setLoggedInUser], [signOutUser, setSignOutUser])}>
         <Router>
    <div className="App">
    <Switch>
      <Route exact path="/">

      <Header></Header>
      <Banner></Banner>
      <Foods></Foods>
      <Features></Features>
      <Footer></Footer>
      </Route>
      <Route path="/user">
        <Login></Login>

      </Route>
      <Route path= "/food/:id">
        <Header cart={cart}></Header>
         
         
         {/* <FoodItemDetails cart={cart} cartHandler={cartHandler}></FoodItemDetails> */}
         <FoodItemDetails cart={cart} cartHandler={cartHandler}></FoodItemDetails>
         <Footer></Footer>

      </Route>
      <Route path ="*">
        <NotFound></NotFound>
      </Route>

    </Switch>
    </div>
    </Router>
     </userContext.Provider>
 
  );
}

export default App;

这是我的 FoodItemDetails.js 文件

import React, { useEffect, useState } from "react";
import { useParams } from "react-router";
// import { useParams } from "react-router";
// import PreLoader from "../PreLoader/PreLoader";
import { FontAwesomeIcon} from '@fortawesome/react-fontawesome'
import { faCartArrowDown, faCheckCircle } from '@fortawesome/free-solid-svg-icons' 
import PreLoader from "../PreLoader/PreLoader";


const FoodItemDetails = (props) => {
  // const {name,shortDescription,price,images} = props.food;

  console.log(props, "nashir")
  const [currentFood, setCurrentFood] = useState({});
  const {id} = useParams();
  console.log(id);
  const [quantity, setQuantity] = useState(1);
  const [isSuccess, setIsSuccess] = useState(false);
  const [selectedBigImage, setSelectedBigImage] = useState(null);
  const [preloaderVisibility, setPreloaderVisibility] = useState("block");
  // const [quantity, setQuantity] = useState(1);
  

  

  useEffect(() => {
    fetch("https://red-onion-backend.herokuapp.com/food/" + id)
      .then((res) => res.json())
      .then((data) => {
        setCurrentFood(data);
        setPreloaderVisibility("none");
      })
      .catch((err) => console.log(err));
    if (currentFood.images) {
      setSelectedBigImage(currentFood.images[0]);
    }
    window.scrollTo(0, 0);
  }, [currentFood.name]);
  const finalCartHandler = (currentFood) => {
    currentFood.quantity = quantity;
    console.log(currentFood, 'food man');
    props.cartHandler = currentFood;
    setIsSuccess(true);
    console.log(isSuccess, "what");
  }
  if(isSuccess){
    setTimeout(() => {

      setIsSuccess(false)
      console.log(isSuccess);
    }, 1500);
  }

  return (
    <div className="food-details container my-5">
      <PreLoader visibility={preloaderVisibility}></PreLoader>
      {currentFood.name && (
        <div className="row">
          <div className="col-md-6 my-5">
            <h1>{currentFood.name}</h1>
            <p className="my-5">{currentFood.fullDescription}</p>
            <div className="d-flex my-4">
              <h2>${currentFood.price.toFixed(2)}</h2>
              <div className="cart-controller ml-3">
                <button
                  className="btn"
                  onClick={() => setQuantity(quantity <= 1 ? 1 : quantity - 1)}
                >
                  -
                </button>
                <button
                  className="btn"
                  onClick={() => setQuantity(quantity + 1)}
                >
                  +
                </button>
              </div>
            </div>
            <div className="action d-flex align-items-center">
                <button className="btn btn-danger btn-rounded" onClick={() => finalCartHandler(currentFood)}><FontAwesomeIcon  icon={faCartArrowDown} /> Add</button>
            </div>
            <div className="more-images mt-5">
              {currentFood.images.map((img, index) => (
                <img
                  onClick={() => setSelectedBigImage(currentFood.images[index])}
                  className={
                    currentFood.images[index] === selectedBigImage
                      ? "mr-4 small-img active-small-img"
                      : "mr-4 small-img"
                  }
                  height="150px"
                  src={img}
                  alt=""
                />
              ))}
            </div>
          </div>
          <div className="col-md-6 my-5">
            <img src={selectedBigImage} className="img-fluid" alt="" />
          </div>
        </div>
      )}
    </div>
  );
};

export default FoodItemDetails;
 
2个回答

首先,您无法更改道具的属性。它们是只读的属性。

第二,您的 carthnadler 是函数而不是属性,而不是分配值而不是调用函数。

246407616

要解决此问题,您需要调用 Carthandler 并通过 Current Food 如下所示: -

488439473
Priyank Kachhela
2021-05-17

Props 是只读属性。在 finalCartHandler 中,您尝试将 props.cartHandler 分配给 currentFood 。我假设您想要调用 props.cartHandler 而不是分配它。

我还注意到在 cartHandler 中,您正在检查 id 是否与 == 相同,这是一个真/假相等,而 === 效果会更好(在其他几个地方也使用 ==!= )。

Kyruski
2021-05-17