首页 > 解决方案 > react redux 中的数据映射有问题吗?

问题描述

我们目前正在使用 react-redux 构建一个电子商务网站。我们使用模拟 JSON 数据来使用 JSON-server 开发产品和类别页面。但是在用真实数据改变数据的同时。那么我们遇到了 typeError 的问题:item.variant 是未定义的。

任何人都可以帮助解决这个问题。

模拟数据:

{
  "product": [
    {
      "id": 1,
      "name": "Flare Dress",
      "price": 120,
      "salePrice": 200,
      "discount": 50,
      "pictures": [
        "/assets/images/fashion/product/1.jpg",
        "/assets/images/fashion/product/21.jpg",
        "/assets/images/fashion/product/36.jpg",
        "/assets/images/fashion/product/12.jpg"
      ],
      "shortDetails": "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt, explicabo. Nemo enim ipsam voluptatem,",
      "description": {
        "Ram": "4gb",
        "size": "large"
      },
      "stock": 16,
      "new": true,
      "sale": true,
      "colors": ["yellow", "gray", "green"],
      "size": ["M", "L", "XL"],
      "tags": ["nike", "caprese"],
      "rating": 4,
      "variants": [
        {
          "color": "yellow",
          "images": "/assets/images/fashion/product/1.jpg"
        },
        {
          "color": "gray",
          "images": "/assets/images/fashion/product/21.jpg"
        },
        {
          "color": "green",
          "images": "/assets/images/fashion/product/36.jpg"
        }
      ]
    },
    {
      "id": 2,
      "name": "Wrap Dress",
      "price": 330.0,
      "salePrice": 165.0,
      "discount": 50,
      "pictures": [
        "/assets/images/fashion/product/15.jpg",
        "/assets/images/fashion/product/7.jpg",
        "/assets/images/fashion/product/9.jpg",
        "/assets/images/fashion/product/13.jpg"
      ],
      "shortDetails": "unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt, explicabo. Nemo enim ipsam voluptatem,",
      "description": {
        "Ram": "4gb",
        "type": "personal",
        "hacker": "world",
        "size": "extralarge"
      },
      "stock": 6,
      "new": true,
      "sale": false,
      "category": "women",
      "colors": ["gray", "orange"],
      "size": ["M", "L", "XL"],
      "tags": ["caprese", "puma"],
      "rating": 5,
      "variants": [
        {
          "color": "gray",
          "images": "/assets/images/fashion/product/15.jpg"
        },
        {
          "color": "orange",
          "images": "/assets/images/fashion/product/7.jpg"
        }
      ]
    },
    {
      "id": 3,
      "name": "Danim Jeans",
      "price": 500.0,
      "salePrice": 250.0,
      "discount": 50,
      "pictures": [
        "/assets/images/fashion/product/32.jpg",
        "/assets/images/fashion/product/2.jpg",
        "/assets/images/fashion/product/25.jpg",
        "/assets/images/fashion/product/26.jpg"
      ],
      "shortDetails": "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt, explicabo. Nemo enim ipsam voluptatem,",
      "description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
      "stock": 12,
      "new": false,
      "sale": false,
      "category": "women",
      "colors": ["blue", "white", "yellow"],
      "size": ["M", "L", "XL"],
      "tags": ["puma"],
      "rating": 4,
      "variants": [
        {
          "color": "blue",
          "images": "/assets/images/fashion/product/32.jpg"
        },
        {
          "color": "white",
          "images": "/assets/images/fashion/product/2.jpg"
        },
        {
          "color": "yellow",
          "images": "/assets/images/fashion/product/25.jpg"
        }
      ]
    },
    {
      "id": 4,
      "name": "Waist Dress",
      "price": 180.0,
      "salePrice": 360.0,
      "discount": 50,
      "pictures": [
        "/assets/images/fashion/product/5.jpg",
        "/assets/images/fashion/product/12.jpg",
        "/assets/images/fashion/product/31.jpg",
        "/assets/images/fashion/product/18.jpg"
      ],
      "shortDetails": "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt, explicabo. Nemo enim ipsam voluptatem,",
      "description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
      "stock": 10,
      "new": true,
      "sale": true,
      "category": "women",
      "colors": ["pink", "gray", "green"],
      "size": ["M", "L", "XL"],
      "tags": ["lifestyle"],
      "rating": 4,
      "variants": [
        {
          "color": "pink",
          "images": "/assets/images/fashion/product/5.jpg"
        },
        {
          "color": "gray",
          "images": "/assets/images/fashion/product/12.jpg"
        },
        {
          "color": "green",
          "images": "/assets/images/fashion/product/31.jpg"
        }
      ]
    }
  ]

真实数据:

{
  "products": [
    {
      "id": 1,
      "active": true,
      "slug": "try",
      "sku": "009993",
      "name": "Samsung s10",
      "price": 220.0,
      "effective_price": 234.0,
      "price_unit": "US Dollar",
      "unit": "pieces",
      "short_description": "My phone",
      "description": "Samsung phone new brand.",
      "for_sale": false,
      "for_sale_percent": 0.0,
      "for_sale_price": 0.0,
      "creation_date": "2020-04-11T14:32:37.397890Z",
      "deliverable": true,
      "stock_amount": 1.0,
      "stock_unit": "pieces",
      "weight": 1.0,
      "weight_unit": "",
      "height": null,
      "height_unit": "",
      "length": null,
      "length_unit": "",
      "width": null,
      "width_unit": "",
      "tax_type": 1,
      "manufacturer": "Samsung",
      "active_sku": true,
      "active_short_description": true,
      "active_description": true,
      "active_effective_price": true,
      "active_dimension": true,
      "active_weight": true,
      "specification": {
        "RAM": "2GB",
        "Display size": "10inch"
      },
      "primary_category": 2,
      "images": [
        {
          "product": 1,
          "name": "try",
          "image_file": "http://eversoftgroup.ddns.net:8000/media/products/before_married_salary_after_married_salary_tVIeusG.jpg"
        },
        {
          "product": 1,
          "name": "dsa",
          "image_file": "http://eversoftgroup.ddns.net:8000/media/products/Unbenannt3.JPG"
        },
        {
          "product": 1,
          "name": "hello",
          "image_file": "http://eversoftgroup.ddns.net:8000/media/main-qimg-e93a7956e2e492201b56d11d8db867bf.png"
        }
      ]
    },
    {
      "id": 2,
      "active": true,
      "slug": "lgmob",
      "sku": "38387",
      "name": "LG Mobile",
      "price": 265.0,
      "effective_price": null,
      "price_unit": "Nepalese Rupee",
      "unit": "23",
      "short_description": "A new mobile",
      "description": "This is a new mobile of LG.",
      "for_sale": false,
      "for_sale_percent": 0.0,
      "for_sale_price": 0.0,
      "creation_date": "2020-04-15T15:14:24.583204Z",
      "deliverable": true,
      "stock_amount": 4.0,
      "stock_unit": "pieces",
      "weight": 1.0,
      "weight_unit": "",
      "height": null,
      "height_unit": "",
      "length": null,
      "length_unit": "",
      "width": null,
      "width_unit": "",
      "tax_type": 1,
      "manufacturer": "LG",
      "active_sku": true,
      "active_short_description": true,
      "active_description": true,
      "active_effective_price": true,
      "active_dimension": true,
      "active_weight": true,
      "specification": {
        "RAM": "3GB",
        "Display size": "5 inch"
      },
      "primary_category": 2,
      "images": []
    }
  ]
}

零件:

    import React, { Component } from "react";
    import Slider from "react-slick";
    import "../common/index.scss";
    import { connect } from "react-redux";

    // import custom Components
    import Service from "./common/service";
    import BrandBlock from "./common/brand-block";
    import NewProduct from "../common/new-product";
    import Breadcrumb from "../common/breadcrumb";
    import DetailsWithPrice from "./common/product/details-price";
    import DetailsTopTabs from "./common/details-top-tabs";
    import { addToCart, addToCartUnsafe, addToWishlist } from "../../actions";
    import ImageZoom from "./common/product/image-zoom";
    import SmallImages from "./common/product/small-image";

    class RightSideBar extends Component {
      constructor() {
        super();
        this.state = {
          nav1: null,
          nav2: null,
        };
      }

      componentDidMount() {
        this.setState({
          nav1: this.slider1,
          nav2: this.slider2,
        });
      }

      render() {
        const {
          symbol,
          item,
          addToCart,
          addToCartUnsafe,
          addToWishlist,
        } = this.props;
        console.log(item.name);
        var products = {
          slidesToShow: 1,
          slidesToScroll: 1,
          dots: false,
          arrows: true,
          fade: true,
        };
        var productsnav = {
          slidesToShow: 3,
          swipeToSlide: true,
          arrows: false,
          dots: false,
          focusOnSelect: true,
        };

        return (
          <div>
            {/* <Breadcrumb title={" Product / " + item.name} /> */}

            {/*Section Start*/}
            {item ? (
              <section className="section-b-space">
                <div className="collection-wrapper">
                  <div className="container">
                    <div className="row">
                      <div className="col-lg-9 col-sm-12 col-xs-12">
                        <div className="container-fluid">
                          <div className="row">
                            <div className="col-xl-12">
                              <div className="filter-main-btn mb-2">
                                <span className="filter-btn">
                                  <i
                                    className="fa fa-filter"
                                    aria-hidden="true"
                                  ></i>{" "}
                                  filter
                                </span>
                              </div>
                            </div>
                          </div>
                          <div className="row">
                            <div className="col-lg-6 product-thumbnail">
                              <Slider
                                {...products}
                                asNavFor={this.state.nav2}
                                ref={(slider) => (this.slider1 = slider)}
                                className="product-slick"
                              >
                                {item.variants.map((vari, index) => (
                                  <div key={index}>
                                    <ImageZoom
                                      image={vari.images}
                                      className="img-fluid image_zoom_cls-0"
                                    />
                                  </div>
                                ))}
                              </Slider>
                              <SmallImages
                                item={item}
                                settings={productsnav}
                                navOne={this.state.nav1}
                              />
                            </div>
                            <DetailsWithPrice
                              symbol={symbol}
                              item={item}
                              navOne={this.state.nav1}
                              addToCartClicked={addToCart}
                              BuynowClicked={addToCartUnsafe}
                              addToWishlistClicked={addToWishlist}
                            />
                          </div>
                        </div>
                        <DetailsTopTabs item={item} />
                      </div>
                      <div className="col-sm-3 collection-filter">
                        {/* <BrandBlock/> */}
                        <Service />
                        {/*side-bar single product slider start*/}
                        <NewProduct />
                        {/*side-bar single product slider end*/}
                      </div>
                    </div>
                  </div>
                </div>
              </section>
            ) : (
              ""
            )}
            {/*Section End*/}
          </div>
        );
      }
    }

    const mapStateToProps = (state, ownProps) => {
      let productId = ownProps.match.params.id;
      return {
        item: state.data.products.find((el) => el.id == productId),
        symbol: state.data.symbol,
      };
    };

    export default connect(mapStateToProps, {
      addToCart,
      addToCartUnsafe,
      addToWishlist,
    })(RightSideBar);
}

标签: javascriptreactjs

解决方案


请尝试使用此更新您的渲染方法


render() {
        const {
          symbol,
          item,
          addToCart,
          addToCartUnsafe,
          addToWishlist,
        } = this.props;
        console.log(item.name);
        var products = {
          slidesToShow: 1,
          slidesToScroll: 1,
          dots: false,
          arrows: true,
          fade: true,
        };
        var productsnav = {
          slidesToShow: 3,
          swipeToSlide: true,
          arrows: false,
          dots: false,
          focusOnSelect: true,
        };

let productVariants = [];
        if(item && item.variants && Array.isArray(item.variants) && item.variants.length > 0)
           productVariants = item.variants.map((vari, index) => (
                                  <div key={index}>
                                    <ImageZoom
                                      image={vari.images}
                                      className="img-fluid image_zoom_cls-0"
                                    />
                                  </div>
                                ))}

        return (
          <div>
            {/* <Breadcrumb title={" Product / " + item.name} /> */}

            {/*Section Start*/}
            {item ? (
              <section className="section-b-space">
                <div className="collection-wrapper">
                  <div className="container">
                    <div className="row">
                      <div className="col-lg-9 col-sm-12 col-xs-12">
                        <div className="container-fluid">
                          <div className="row">
                            <div className="col-xl-12">
                              <div className="filter-main-btn mb-2">
                                <span className="filter-btn">
                                  <i
                                    className="fa fa-filter"
                                    aria-hidden="true"
                                  ></i>{" "}
                                  filter
                                </span>
                              </div>
                            </div>
                          </div>
                          <div className="row">
                            <div className="col-lg-6 product-thumbnail">
                              <Slider
                                {...products}
                                asNavFor={this.state.nav2}
                                ref={(slider) => (this.slider1 = slider)}
                                className="product-slick"
                              >
                                {productVariants}
                              </Slider>
                              <SmallImages
                                item={item}
                                settings={productsnav}
                                navOne={this.state.nav1}
                              />
                            </div>
                            <DetailsWithPrice
                              symbol={symbol}
                              item={item}
                              navOne={this.state.nav1}
                              addToCartClicked={addToCart}
                              BuynowClicked={addToCartUnsafe}
                              addToWishlistClicked={addToWishlist}
                            />
                          </div>
                        </div>
                        <DetailsTopTabs item={item} />
                      </div>
                      <div className="col-sm-3 collection-filter">
                        {/* <BrandBlock/> */}
                        <Service />
                        {/*side-bar single product slider start*/}
                        <NewProduct />
                        {/*side-bar single product slider end*/}
                      </div>
                    </div>
                  </div>
                </div>
              </section>
            ) : (
              ""
            )}
            {/*Section End*/}
          </div>
        );
      }




推荐阅读