React Redux-无法设置未定义的属性“数量”

时间:2019-09-08 22:12:12

标签: reactjs react-redux react-router

我正在使用React,Redux和React-Router建立一个电子商务网站。到目前为止,我有一个包含所有项目的主页以及一个将这些项目添加到购物车的链接。每个商品的商品详细信息页面有<Link>个,并且该商品详细信息页面上还有一个“添加到购物车”按钮。

我需要执行addToCart操作以获取正在查看的商品的ID,并将其添加到购物车中。我的问题是,在“商品详细信息”页面上,单击“添加到购物车”按钮时,我收到cartReducer.js文件的此TypeError: TypeError:无法设置未定义的属性“ quantity”

这仅在项目详细信息页面上发生,而不是在主页上发生。我觉得这与以下事实有关:所有项都是从主页上的map()函数呈现的...?

在项目详细信息页面上,根据从首页的location.state传递的道具(<Link>)渲染项目。我无法弄清楚如何将商品ID从URL传递到addToCart操作,而不会引发错误。


这是我到目前为止尝试过的:

Item.js

ownProps

我意识到尝试上述操作并不适合我,因此我已经从const mapStateToProps = (state, ownProps) => {     return {         items: state.items,         id: ownProps.id === state.id // I've also tried id: ownProps.id     }; } 的{​​{1}}中抽走了ownProps

今天,我已经阅读了许多其他关于该主题的SO问题与解答以及参考文章,但是我已经失去了对所有引用内容的跟踪。

我只是不明白为什么无法将Item ID从Item.js传递到reducer,但它对于Home.js来说效果很好


我已将代码放在此处的codeandbox上:

https://codesandbox.io/s/github/thesemdrnsocks/redux-co

到目前为止,这是我的代码:

Item.js (提供“商品详细信息”页面-无法从此组件向购物车添加商品)

mapStateToProps()

Home.js (提供显示商店中所有商品的主页-从此处向购物车添加商品)

Item.js

cartReducer.js (摘录)

import React from 'react';
import { connect } from 'react-redux';
import {
    Link,
    withRouter
} from 'react-router-dom';
import { addToCart } from '../../actions/CartActions';

const mapStateToProps = (state, ownProps) => {
    return {
        items: state.items,
        id: ownProps.id === state.id
    };
}

const mapDispatchToProps = (dispatch) => {
    return {
        addToCart: (id) => { dispatch(addToCart(id)) }
    };
}

class Item extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            item: this.props.location.state,
        }

    }

    handleAddToCart = (id) => {
        this.props.addToCart(id);
    }

    render() {
        const item = this.state.item;
        return (
            <div className="item-details" key={item.id}>
                <div className="item-details-img">
                    <img src={item.img} alt={item.title} />
                </div>
                <div className="item-details-info">
                    <p className="item-details-title">{item.title}</p>
                    <p className="item-details-price"><b>${item.price}</b></p>
                    <p className="item-details-desc">{item.desc}</p>
                    <div className="item-details-add-to-cart">
                        <Link to="/cart" onClick={ () => { this.handleAddToCart(item.id) } }>
                            <button>Add to Bag</button>
                        </Link>
                    </div>
                </div>
            </div>
        );
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Item));

ShopContent.js (摘录;保存商品信息)

import React from 'react';
import { connect } from 'react-redux';
import {
    Link,
    withRouter
} from 'react-router-dom';
import { addToCart } from '../actions/CartActions';
import Item from './shopping/Item';

const mapStateToProps = (state) => {
    return {
        items: state.items
    };
}

const mapDispatchToProps = (dispatch) => {
    return {
        addToCart: (id) => { dispatch(addToCart(id)) }
    };
}

class Home extends React.Component {
    handleAddToCart = (id) => {
        this.props.addToCart(id);
    }

    render() {
        let itemList = this.props.items.map(item =>{
            return (
                <div className="home-item-card" key={item.id}>
                    <div className="home-item-image">
                        <Link to = 
                            {{ pathname: `/products/${item.category}`,
                            search: `?id=${item.id}`,
                            state: {
                                id: `${item.id}`,
                                img: `${item.img}`,
                                title: `${item.title}`, 
                                desc: `${item.desc}`,
                                price: `${item.price}`
                            } }}
                            component={ Item }>
                                <img src={item.img} alt={item.title} />
                        </Link>
                    </div>
                    <div className="home-item-info">
                        <span className="home-item-title">{item.title}</span>
                        <Link to="/" className="home-add-item" onClick={() => 
                            { this.handleAddToCart(item.id) } }>
                            <i class="fa fa-plus-circle"></i>
                        </Link>
                        <p className="home-item-price"><b>${item.price}</b></p>
                        <p className="home-item-desc">{item.desc}</p>
                    </div>
                </div>
            )
        })

        return (
            <div className="home-new-arrivals">
                <h1>What's new?</h1>
                <div className="new-arrivals-items">
                    {itemList}
                </div>
            </div>
        );
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Home));

2 个答案:

答案 0 :(得分:1)

这是您的问题,当您传递到import json inp = input('Enter a dictionary') inp = dict(json.loads(inp)) sum = sum(inp.values()) print(sum) 组件时,会更改item.id的数据类型。您会将所选项目作为字符串放入位置记录中。但是然后在化简器中对要转换为整数的整数进行Item操作,将无法正常工作。 (又名===)。

1 === '1'

几种解决此问题的方法。
1. Pull the item from your actual state based on the id in the URL
2.调度一个活动项目操作,该操作将使用您正在查看的活动项目更新您的reducer。

我认为第一个选择非常简单,并且对您的代码进行的更改更少,这就是它的样子。

<Link to={
  { pathname: `/products/${item.category}`,
    search: `?id=${item.id}`,
    state: {
      id: `${item.id}`,
      img: `${item.img}`,
      title: `${item.title}`, 
      desc: `${item.desc}`,
      price: `${item.price}`
    }
  }}
  component={ Item }
>
  <img src={item.img} alt={item.title} />
</Link>

然后在项目中

// Home
<Link
  to={{
    pathname: `/products/${item.category}`,
    search: `?id=${item.id}`
  }}
  component={Item}
>
  <img src={item.img} alt={item.title} />
</Link> 

答案 1 :(得分:0)

我确实感觉这是您的问题所在,您正在将boolean值传递给id道具。它应该是ownProps.idstate.id

const mapStateToProps = (state, ownProps) => {
    return {
        items: state.items,
        id: ownProps.id === state.id
    };
}