无法从状态片段访问对象属性。

huangapple go评论51阅读模式
英文:

Can't access object properties from state slice

问题

我正在尝试使用Redux-Toolkit为我的Web应用程序制作购物车切片。在我的cartSlice.js文件中,我希望能够实现向购物车添加/移除商品,并且如果购物车中已经有商品,还能够增加/减少商品的数量。我遇到的主要问题是无法从cartSlice.js文件中访问quantity属性。

以下是cart和cartSlice文件的代码,以及item组件和storeItems文件,storeItems文件是存储商品对象的数组。

cart.js:
```javascript
import { React } from 'react';
import { useSelector } from "react-redux";
import { selectCart } from './cartSlice';


export const Cart = () => {
    const cart = useSelector(selectCart);

    return (
        <div className="cart">
            {cart.cart?.map( (item) => (
                <p quantity={item.quantity} >{item.name} x{item.quantity}</p>
            ))}
        </div>
    )
}

cartSlice.js:

import { createSlice } from '@reduxjs/toolkit';


const cartSlice = createSlice({
    name: 'cart',
    initialState: {
        cart: [],
        total: 0,
    },
    reducers: {
        addToCart: (state, action) => {
            const itemInCart = state.cart.find((item) => item.id === action.payload.id);
            const item = state.cart.find((item) => item.id === action.payload);

            if (itemInCart > 1) {
                state.total += action.payload.price;
                item.quantity += 1;
            } else {
                state.cart.push({ ...action.payload, quantity:  1});
                state.total += action.payload.price;
                item.quantity += 1;
            }
        },
        removeItem: (state, action) => {
            const itemInCart = state.cart.find((item) => item.id === action.payload.id);
            const item = state.cart.find((item) => item.id === action.payload);

            if (itemInCart.quantity === 1) {
                const removeItem = state.cart.filter((item) => item.id !== action.payload.id);
                state.cart = removeItem;
                state.total -= action.payload.price;
                item.quantity -= 1;
            } else {
                item.quantity -= 1;
            }  
        },
    },
})

export const { addToCart, incrementQuantity, decrementQuantity, removeItem } = cartSlice.actions;
export const selectCart = (state) => state.cart;
export const cartReducer = cartSlice.reducer;

Item.js:

import { React } from 'react';
import styles from '../../styles/shopping.module.css';
import { addToCart, removeItem } from '../../features/Shopping/cart/cartSlice';
import { useDispatch } from "react-redux";


export default function Item({item}) {
    const dispatch = useDispatch();

    const onAddToCartHandler = (item) => {
        dispatch(addToCart(item));
    }
    const onRemoveFromCartHandler = (item) => {
        dispatch(removeItem(item));
    }

    return (
        <div key={item.id} className={styles.item}>
            {/* <img src={require('../../styles/image-not-found.jpg')} /> */}
            <img src={item.image} />
            <h3>{item.name}</h3>
            <p>Price: ${item.price}</p>
            <div className="buttons">
                    <button onClick={() => onAddToCartHandler(item)}>+</button>
                    <button onClick={() => onRemoveFromCartHandler(item)}>-</button>
            </div>
        </div>
    )
}

storeItems.js:

export const produce = [
    {
        id: 1,
        name: "Carrots",
        price: 2.89,
        image: "https://www.jessicagavin.com/wp-content/uploads/2019/02/carrots-7-1200.jpg",
        quantity: 0,
    },
    {
        id: 2,
        name: "Cucumbers",
        price: 0.99,
        image: "https://snaped.fns.usda.gov/sites/default/files/styles/crop_ratio_7_5/public/seasonal-produce/2018-05/cucumbers2.jpg?itok=YISLeW4e",
        quantity: 0,
    },
    {
        id: 3,
        name: "Bell peppers",
        price: 0.76,
        image: "https://hosstools.com/wp-content/uploads/2020/10/mini-belle-pepper-mix.jpg",
        quantity: 0,
    },
    {
        id: 4,
        name: "Avocados",
        price: 1.26,
        image: "https://blog.lexmed.com/images/librariesprovider80/blog-post-featured-images/avocadosea5afd66b7296e538033ff0000e6f23e.jpg?sfvrsn=a273930b_0",
        quantity: 0,
    },
    {
        id: 5,
        name: "Spinach",
        price: 2.99,
        image: "https://cdn.britannica.com/30/82530-050-79911DD4/Spinach-leaves-vitamins-source-person.jpg",
        quantity: 0,
    },
    {
        id: 6,
        name: "Kale",
        price: 2.30,
        image: "https://i0.wp.com/images-prod.healthline.com/hlcmsresource/images/AN_images/benefits-of-kale-1296x728-feature.jpg?w=1155&h=1528",
        quantity: 0,
    },
    {
        id: 7,
        name: "Tomatoes",
        price: 1.05,
        image: "https://www.almanac.com/sites/default/files/styles/or/public/image_nodes/tomatoes_helios4eos_gettyimages-edit.jpeg?itok=2owPswip",
        quantity: 0,
    }
]

<details>
<summary>英文:</summary>
I am trying to make a shopping cart slice for my web application using Redux-Toolkit. In my cartSlice.js file, I would like to have the functionality to be able to add/remove items to the cart, and increment/decrement the quantity of the items if there are already items in the cart. The main issue I am running into is not being able to access the quantity property from the cartSlice.js file. 
Below is the code for the cart &amp; cartSlice files, as well as the item component and storeItems file which is an array of objects the store has.
cart.js:

import { React } from 'react';
import { useSelector } from "react-redux";
import { selectCart } from './cartSlice';

export const Cart = () => {
const cart = useSelector(selectCart);

return (
&lt;div className=&quot;cart&quot;&gt;
{cart.cart?.map( (item) =&gt; (
&lt;p quantity={item.quantity} &gt;{item.name} x{item.quantity}&lt;/p&gt;
))}
&lt;/div&gt;
)

}

cartSlice.js:

import { createSlice } from '@reduxjs/toolkit';

const cartSlice = createSlice({
name: 'cart',
initialState: {
cart: [],
total: 0,
},
reducers: {
addToCart: (state, action) => {
const itemInCart = state.cart.find((item) => item.id === action.payload.id);
const item = state.cart.find((item) => item.id === action.payload);

        if (itemInCart &gt; 1) {
state.total += action.payload.price;
item.quantity += 1;
} else {
state.cart.push({ ...action.payload, quantity:  1});
state.total += action.payload.price;
item.quantity += 1;
}
},
removeItem: (state, action) =&gt; {
const itemInCart = state.cart.find((item) =&gt; item.id === action.payload.id);
const item = state.cart.find((item) =&gt; item.id === action.payload);
if (itemInCart.quantity === 1) {
const removeItem = state.cart.filter((item) =&gt; item.id !== action.payload.id);
state.cart = removeItem;
state.total -= action.payload.price;
item.quantity -= 1;
} else {
item.quantity -= 1;
}  
},
},

})

export const { addToCart, incrementQuantity, decrementQuantity, removeItem } = cartSlice.actions;
export const selectCart = (state) => state.cart;
export const cartReducer = cartSlice.reducer;

Item.js:

import { React } from 'react';
import styles from '../../styles/shopping.module.css';
import { addToCart, removeItem } from '../../features/Shopping/cart/cartSlice';
import { useDispatch } from "react-redux";

export default function Item({item}) {
const dispatch = useDispatch();

const onAddToCartHandler = (item) =&gt; {
dispatch(addToCart(item));
}
const onRemoveFromCartHandler = (item) =&gt; {
dispatch(removeItem(item));
}
return (
&lt;div key={item.id} className={styles.item}&gt;
{/* &lt;img src={require(&#39;../../styles/image-not-found.jpg&#39;)} /&gt; */}
&lt;img src={item.image} /&gt;
&lt;h3&gt;{item.name}&lt;/h3&gt;
&lt;p&gt;Price: ${item.price}&lt;/p&gt;
&lt;div className=&quot;buttons&quot;&gt;
&lt;button onClick={() =&gt; onAddToCartHandler(item)}&gt;+&lt;/button&gt;
&lt;button onClick={() =&gt; onRemoveFromCartHandler(item)}&gt;-&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
)

}

storeItems.js:

export const produce = [
{
id: 1,
name: "Carrots",
price: 2.89,
image: "https://www.jessicagavin.com/wp-content/uploads/2019/02/carrots-7-1200.jpg",
quantity: 0,
},
{
id: 2,
name: "Cucumbers",
price: 0.99,
image: "https://snaped.fns.usda.gov/sites/default/files/styles/crop_ratio_7_5/public/seasonal-produce/2018-05/cucumbers2.jpg?itok=YISLeW4e",
quantity: 0,
},
{
id: 3,
name: "Bell peppers",
price: 0.76,
image: "https://hosstools.com/wp-content/uploads/2020/10/mini-belle-pepper-mix.jpg",
quantity: 0,
},
{
id: 4,
name: "Avocados",
price: 1.26,
image: "https://blog.lexmed.com/images/librariesprovider80/blog-post-featured-images/avocadosea5afd66b7296e538033ff0000e6f23e.jpg?sfvrsn=a273930b_0",
quantity: 0,
},
{
id: 5,
name: "Spinach",
price: 2.99,
image: "https://cdn.britannica.com/30/82530-050-79911DD4/Spinach-leaves-vitamins-source-person.jpg",
quantity: 0,
},
{
id: 6,
name: "Kale",
price: 2.30,
image: "https://i0.wp.com/images-prod.healthline.com/hlcmsresource/images/AN_images/benefits-of-kale-1296x728-feature.jpg?w=1155&h=1528",
quantity: 0,
},
{
id: 7,
name: "Tomatoes",
price: 1.05,
image: "https://www.almanac.com/sites/default/files/styles/or/public/image_nodes/tomatoes_helios4eos_gettyimages-edit.jpeg?itok=2owPswip",
quantity: 0,
}
]


</details>
# 答案1
**得分**: 2
你提到了一些代码部分。你提到了后端工作正常,但在状态中无法访问数量属性。这是因为你在cartSlice.js文件中犯了一个小错误。
在item.js中的dispatch方法中,你将整个Item对象传递给了reducers函数,但在find方法中,你在item变量中将item.id与整个item对象进行匹配。所以它永远不会找到任何项。
你已经这样做了...
dispatch(addToCart(item));
你传递了整个对象。
而不是这样使用,也许它会让你访问到数量。
你已经这样做了...
const item = state.cart.find((item) => item.id === action.payload);
应该这样做...
const item = state.cart.find((item) => item.id === action.payload.id);
而且如果你发现任何问题,请尝试在reducer中记录action以查看你得到了什么...
谢谢...
<details>
<summary>英文:</summary>
As you have mentioned only some files code.You mentioned your backend working fine but in state you can&#39;t access quantity attribute. Its because of you have made small mistake in you cartSlice.js file.
In item.js in dispatch method you have passed whole Item object to the reducers function, but in find method method in item variable you are matching item.id with whole item object. So its never gonna find any item. 
You have done this...
dispatch(addToCart(item));
You have passed whole object.
Instead of that use like this, may be it will give you access to the quantity.
You have done this..
const item = state.cart.find((item) =&gt; item.id === action.payload);
Do like this...
const item = state.cart.find((item) =&gt; item.id === action.payload.id); 
also if you find any problems, try to log action in reducer to see what you are getting... 
Thank you...
</details>

huangapple
  • 本文由 发表于 2023年5月22日 23:23:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76307700.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定