You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React组件间传递排序函数实现产品升降序排序?

问题修复与优化方案

核心问题定位

  • MainContentHeader状态更新未执行:下拉选择的switch分支中仅定义匿名函数,未实际调用setSorting,导致父组件排序状态从未更新。
  • 数组排序违反不可变原则:sortProductList.sort(currentFuncOfSorting)是原地排序操作,会直接修改state中的原数组,引发状态异常。
  • 初始状态未处理:currentSorting初始值为undefined,触发useEffect时会导致排序函数调用报错。
  • 冗余状态维护:ProductSection中维护sortProductList状态易与原始productList不同步,增加维护成本。

分步修复与优化

1. 修复MainContentHeader的状态更新逻辑

将匿名函数改为直接调用setSorting,同时处理默认选项的重置逻辑:

// MainContentHeader.jsx
<select
  onChange={(e) => {
    switch (e.target.value) {
      case "price:asc":
        setSorting(SortPriceAsc);
        break;
      case "price:desc":
        setSorting(SortPriceDesc);
        break;
      default:
        setSorting(null); // 默认排序重置为原始顺序
    }
  }}
  className="main-content-header__order"
>
  <option data-filter-value="" value="">
    Order: Default
  </option>
  <option data-filter-value="price:asc" value="price:asc">
    Price: ascending
  </option>
  <option data-filter-value="price:desc" value="price:desc">
    Price: descending
  </option>
</select>

2. 优化ProductSection的排序逻辑与状态管理

移除冗余的sortProductList状态,基于原始productList和当前排序函数计算结果,同时遵守状态不可变原则:

// ProductSection.jsx
import { useMemo, useEffect, useState } from 'react';

export default function ProductSection({ currentFuncOfSorting }) {
  const [limitedProductList, setProductsToShow] = useState([]);
  const [next, setNext] = useState(initialCountProducts);

  // 用useMemo缓存排序结果,避免重复计算
  const sortedProductList = useMemo(() => {
    if (!currentFuncOfSorting) return [...productList]; // 默认返回原始数组副本
    // 先复制数组再排序,避免修改原productList
    return [...productList].sort(currentFuncOfSorting);
  }, [currentFuncOfSorting]);

  // 排序变化时重置显示内容和加载位置
  useEffect(() => {
    setProductsToShow(sortedProductList.slice(0, initialCountProducts));
    setNext(initialCountProducts);
  }, [sortedProductList]);

  const handleShowMorePosts = () => {
    const newNext = next + productsPerСlick;
    setProductsToShow(sortedProductList.slice(0, newNext));
    setNext(newNext);
  };

  return (
    <>
      <section className="product-section">
        {limitedProductList.map((item) => (
          <ProductCard key={item.id} {...item} /> {/* 建议用产品唯一ID作为key,替代index */}
        ))}
      </section>
      {limitedProductList.length < sortedProductList.length && (
        <div className="product-section__button">
          <button onClick={handleShowMorePosts}>Upload more</button>
        </div>
      )}
    </>
  );
}

3. 完善父组件初始状态

给currentSorting设置初始值,避免undefined引发的潜在错误:

// HomePage.jsx
export default function HomePage() {
  // 默认设为null对应原始排序,也可传入默认排序函数
  const [currentSorting, setCurrentSorting] = useState(null);

  return (
    <>
      <IntroSlider />
      <main className="main-content">
        <MainContentHeader setSorting={setCurrentSorting} />
        <ProductSection currentFuncOfSorting={currentSorting} />
      </main>
    </>
  );
}

额外优化建议

  • 替换列表key:用产品的唯一标识(如item.id)替代index作为组件key,确保列表更新的性能和正确性。
  • 封装排序函数:将SortPriceAsc和SortPriceDesc抽离到工具文件中,便于复用和维护:
    // utils/sortFunctions.js
    export const SortPriceAsc = (a, b) => a.price - b.price;
    export const SortPriceDesc = (a, b) => b.price - a.price;
    
  • 添加类型约束:使用PropTypes或TypeScript为组件props添加类型检查,提前发现潜在错误。

内容的提问来源于stack exchange,提问作者Animeybe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 15:47:33