老师,引用 ProductList 组件之后报错

老师,引用 ProductList 组件之后报错

https://img1.sycdn.imooc.com//climg/62cf970209d2c82819201030.jpg


另外还有个疑问,页面组件 ShoppingCart 引入 ProductList 组件时传入的 props 的值是一个由 id 字符串类型组成的数组,而 ProductList 组件接收的 props 类型是一个由对象类型组成的数组,感觉 ShoppingCart 传入的 props 没有符合 ProductList 组件的 props 的要求,这个就很疑惑为什么还可以渲染上这个组件的

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
好帮手慕星星 2022-07-14 14:06:51

同学你好,报错的意思是无法读取属性值

https://img1.sycdn.imooc.com//climg/62cfafa809e44ff804560031.jpg

可能数据没有传递过来,建议将ProductList.tsx以及ShoppingCart.tsx代码粘贴上来,便于帮助测试。

ProductList组件中对传过来的props,在参数中直接解构了而已

https://img1.sycdn.imooc.com//climg/62cfb25909f4a37005630161.jpg

祝学习愉快!

  • 提问者 dawn_eve #1

    ShoppingCart.tsx

    import React from "react";
    import styles from './ShoppingCartPage.module.css';
    import { MainLayout } from "../../layouts/mainLayout";
    import { Row, Col, Affix } from "antd";
    import { ProductList, PaymentCard } from "../../components";
    import { useSelector } from '../../redux/hooks';
    import { useDispatch } from "react-redux";
    import { clearShoppingCart } from "../../redux/shoppingCart/slice";
    
    export const ShoppingCartPage : React.FC = () => {
      const loading = useSelector(s => s.shoppingCart.loading);
      const shoppingCartItems = useSelector(s => s.shoppingCart.items);
      const jwt = useSelector(s => s.user.token);
      const dispatch = useDispatch();
    
      // console.log('shoppingCartItems', shoppingCartItems.map(s => s.touristRouteId));
      // console.log('shoppingCartItems', shoppingCartItems);
    
      return (
        <MainLayout>
          <Row>
            {/* 购物车清单 */}
            <Col span={16}>
              <div className={styles["product-list-container"]}>
                <ProductList data={shoppingCartItems.map(s => s.touristRouteId)} />
              </div>
            </Col>
            {/* 支付卡组件 */}
            <Col span={8}>
              <Affix>
                <div className={styles["payment-cart-container"]}>
                  <PaymentCard
                    loading={loading}
                    // 原价 originalPrice ➡ 为所有线路的总价
                    originalPrice={shoppingCartItems
                      .map(s => s.originalPrice)
                      .reduce((a, b) => a + b, 0)}
                    // 折扣过后的价格
                    price={shoppingCartItems
                      .map(
                        s => s.originalPrice *
                        (s.discountPresent ? s.discountPresent : 1)
                      )
                      .reduce((a, b) => a + b, 0)}
                    // 用户点击下单按钮处理事件 onCheckout
                    onCheckout={() => {
                     
                    }}
                    // 清空购物车事件 
                    onShoppingCartClear={() => {
                      dispatch(clearShoppingCart({jwt, itemIds: shoppingCartItems.map(s => s.id)}))
                    }}
                  />
                </div>
              </Affix>
            </Col>
          </Row>
        </MainLayout>
      )
    }


    ProductList.tsx

    import React from "react";
    import { Link } from "react-router-dom";
    import { List, Rate, Space, Image, Tag, Typography } from "antd";
    import { MessageOutlined, LikeOutlined, StarOutlined } from "@ant-design/icons";
    
    const { Text } = Typography;
    
    interface Product {
      departureCity: string;
      description: string;
      discountPresent: number;
      id: string;
      originalPrice: number;
      price: number;
      rating: number;
      title: string;
      touristRoutePictures: any[];
      travelDays: string;
      tripType: string;
    }
    interface PropsType {
      data: Product[] | string[];
      paging?: any; // 修改为可选参数
      onPageChange?: (nextPage, pageSize) => void;
    }
    
    const listData = (productList: Product[] | string[]) =>
      productList.map((p) => ({
        id: p.id,
        title: p.title,
        description: p.description,
        tags: (
          <>
            {p.departureCity && <Tag color="#f50">{p.departureCity}出发</Tag>}
            {p.travelDays && <Tag color="#108ee9">{p.travelDays} 天 </Tag>}
            {p.discountPresent && <Tag color="#87d068">超低折扣</Tag>}
            {p.tripType && <Tag color="#2db7f5">{p.tripType}</Tag>}
          </>
        ),
        imgSrc: p.touristRoutePictures[0].url,
        price: p.price,
        originalPrice: p.originalPrice,
        discountPresent: p.discountPresent,
        rating: p.rating,
      }));
    
    const IconText = ({ icon, text }) => (
      <Space>
        {React.createElement(icon)}
        {text}
      </Space>
    );
    
    export const ProductList: React.FC<PropsType> = ({
      data,
      paging,
      onPageChange,
    }) => {
      const products = listData(data);
      return (
        <List
          itemLayout="vertical"
          size="large"
          pagination={
            // 判断是否传入 paging
            paging
            ? {
                current: paging.currentPage,
                onChange: (page) => onPageChange && onPageChange(page, paging.pageSize),
                pageSize: paging.pageSize,
                total: paging.totalCount,
              }
            : false
          }
          dataSource={products}
          footer={
            /* 有且只有 paging 不为空时才显示 footer */
            paging && (
              <div>
                搜索总路线: <Text strong>{paging.totalCount}</Text> 条
              </div>
            )
          }
          renderItem={(item) => (
            <List.Item
              key={item.title}
              actions={[
                <IconText
                  icon={StarOutlined}
                  text="156"
                  key="list-vertical-star-o"
                />,
                <IconText
                  icon={LikeOutlined}
                  text="156"
                  key="list-vertical-like-o"
                />,
                <>
                  <Rate defaultValue={3} />
                  <Text strong className="ant-rate-text">
                    {item.rating}
                  </Text>
                </>,
              ]}
              extra={
                <Image width={272} height={172} alt="image" src={item.imgSrc} />
              }
            >
              <List.Item.Meta
                title={
                  <>
                    {item.discountPresent ? (
                      <>
                        <Text style={{ fontSize: 20, fontWeight: 400 }} delete>
                          ¥ {item.originalPrice}
                        </Text>
                        <Text
                          type="danger"
                          style={{ fontSize: 20, fontWeight: 400 }}
                        >
                          {" "}
                          ¥ {item.price}
                        </Text>
                      </>
                    ) : (
                      <Text style={{ fontSize: 20, fontWeight: 400 }}>
                        ¥ {item.price}
                      </Text>
                    )}
                    <Link to={"/detail/" + item.id}> {item.title}</Link>
                  </>
                }
                description={item.tags}
              />
              {item.description}
            </List.Item>
          )}
        />
      );
    };



    2022-07-14 14:16:55
  • 提问者 dawn_eve #2

    我输出了 ShoppingCart 传递过来的 props 是这样的:

    https://img1.sycdn.imooc.com//climg/62cfb7540933034811490129.jpg

    但是 data 要经过 listData 方法进行数据转换再输出的:

    const listData = (productList: Product[] | string[]) =>
      productList.map((p) => ({
        id: p.id,
        title: p.title,
        description: p.description,
        tags: (
          <>
            {p.departureCity && <Tag color="#f50">{p.departureCity}出发</Tag>}
            {p.travelDays && <Tag color="#108ee9">{p.travelDays} 天 </Tag>}
            {p.discountPresent && <Tag color="#87d068">超低折扣</Tag>}
            {p.tripType && <Tag color="#2db7f5">{p.tripType}</Tag>}
          </>
        ),
        imgSrc: p.touristRoutePictures[0].url,
        price: p.price,
        originalPrice: p.originalPrice,
        discountPresent: p.discountPresent,
        rating: p.rating,
      }));

    然后,上面可以看到 data 的属性是一个包含 3 个 ID 值的字符串类型的数组,并不能使用 listData 的方法进行转换啊

    https://img1.sycdn.imooc.com//climg/62cfb899093d476c08690835.jpg

    2022-07-14 14:33:16
  • 好帮手慕星星 回复 提问者 dawn_eve #3

    ShoppingCart组件中传的data数据不对,应该是整个数据,不能只传id值

    https://img1.sycdn.imooc.com//climg/62cfbfda09c5d09709970138.jpg

    https://img1.sycdn.imooc.com//climg/62cfc01e09c67cfd17140147.jpg

    2022-07-14 15:05:11
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师