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

React组件非预期重渲染问题:点击Price区域输入控件后filtersection状态被重置为categories

问题根源与修复方案

我一眼就看出问题出在哪了——你把leftSideBar和rightSideBar这两个组件定义在了父组件的内部!

为什么会出现状态重置的情况?

每次父组件发生重渲染(比如你点击Price区域的输入控件触发handlePrice,进而导致父组件状态更新),这两个内部定义的组件都会被重新创建成全新的函数。React会把旧的组件实例卸载,再挂载新的组件实例——这就相当于整个侧边栏被“重启”了一遍,关联的filtersection状态自然就回到初始值"categories"了。

修复方案(推荐第一种)

方案1:将子组件移到父组件外部

把leftSideBar和rightSideBar提取成独立的组件,通过props传递需要的状态和回调函数。这样组件不会随着父组件重渲染而被重新创建,状态关联会保持稳定:

// 独立定义子组件,放在父组件外部
const LeftSideBar = ({ setFilterSection }) => {
  return (
    <div className="leftsidebarbody">
      <div onClick={() => setFilterSection("categories")}>Categories</div>
      <div onClick={() => setFilterSection("prices")}>Price</div>
    </div>
  );
};

const RightSideBar = ({ 
  filtersection, 
  categories, 
  selectedCategories, 
  handleCheck, 
  prices, 
  selectedPrice, 
  handlePrice 
}) => {
  return (
    <div className="rightsidebarbody">
      {filtersection === "categories" && (
        <div className="block">
          {categories.map((category, index) => {
            return (
              <div className="categories" key={index}>
                <input 
                  type="checkbox" 
                  id={category._id} 
                  onChange={handleCheck} 
                  checked={selectedCategories.includes(category._id)} 
                />
                <div>{category.name}</div>
              </div>
            );
          })}
        </div>
      )}
      {filtersection === "prices" && (
        <div className="block">
          {prices.map((price, index) => {
            return (
              <div className="categories" key={index}>
                <input 
                  name={price} 
                  value={`${price._id}`} 
                  type="radio" 
                  onChange={handlePrice} 
                  checked={selectedPrice.includes(price._id)} 
                />
                {price.name}
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
};

// 父组件中使用子组件
const ParentComponent = () => {
  const [filtersection, setFilterSection] = React.useState("categories");
  // 假设你已经定义了以下状态和回调:
  // const [categories, setCategories] = React.useState([]);
  // const [selectedCategories, setSelectedCategories] = React.useState([]);
  // const handleCheck = () => { /* ... */ };
  // const [prices, setPrices] = React.useState([]);
  // const [selectedPrice, setSelectedPrice] = React.useState([]);
  // const handlePrice = () => { /* ... */ };

  return (
    <div className="parent-container">
      <LeftSideBar setFilterSection={setFilterSection} />
      <RightSideBar 
        filtersection={filtersection}
        categories={categories}
        selectedCategories={selectedCategories}
        handleCheck={handleCheck}
        prices={prices}
        selectedPrice={selectedPrice}
        handlePrice={handlePrice}
      />
    </div>
  );
};

方案2:若必须留在父组件内部,用useMemo缓存组件

如果因为某些原因(比如需要访问父组件的私有变量)必须把组件定义在父组件内部,那么可以用useMemo来缓存组件实例,避免每次重渲染都重新创建:

const ParentComponent = () => {
  const [filtersection, setFilterSection] = React.useState("categories");
  // 其他状态和回调...

  // 用useMemo缓存LeftSideBar组件
  const LeftSideBar = React.useMemo(() => {
    return () => (
      <div className="leftsidebarbody">
        <div onClick={() => setFilterSection("categories")}>Categories</div>
        <div onClick={() => setFilterSection("prices")}>Price</div>
      </div>
    );
  }, [setFilterSection]);

  // 用useMemo缓存RightSideBar组件
  const RightSideBar = React.useMemo(() => {
    return () => (
      <div className="rightsidebarbody">
        {/* 原有内容不变 */}
      </div>
    );
  }, [filtersection, categories, selectedCategories, handleCheck, prices, selectedPrice, handlePrice]);

  return (
    <div>
      <LeftSideBar />
      <RightSideBar />
    </div>
  );
};

额外优化建议

为了避免不必要的重渲染,你还可以用React.useCallback包裹handleCheck和handlePrice这两个回调函数,确保它们不会在父组件重渲染时被频繁重新创建:

const handleCheck = React.useCallback((e) => {
  // 你的原有逻辑
}, [selectedCategories]);

const handlePrice = React.useCallback((e) => {
  // 你的原有逻辑
}, [selectedPrice]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 11:28:11