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

React useState更新延迟点击生效问题及双useEffect合并诉求

问题分析与解决方案

核心问题原因

  1. 直接修改State对象:你在useEffect里直接修改rowData的属性(如rowData[rowKey] = { ...rowData[rowKey], isHidden: false }),这属于篡改状态,React无法检测到对象内部的变化,导致组件不触发重新渲染,所以第一次点击下拉无反应,第二次点击时依赖项变化才会渲染,显示之前的操作结果。
  2. 筛选逻辑互相覆盖:两个useEffect分别处理分类和SDLR筛选,每次触发都会重置所有行的isHidden,导致另一个筛选的结果被覆盖,比如选择People分类后,SDLR的useEffect会把所有行的isHidden重置为false,破坏分类筛选的结果。
  3. 未保存原始数据:每次筛选都是基于修改后的rowData,导致原始数据被污染,无法正确恢复全量数据。

修复后的完整代码

import { React, useEffect, useState, useMemo } from "react";
import TableRow from "../../components/TableRow/TableRow";
import axios from "axios";

export default function SellerList() {
  // 保存原始接口数据,不做任何修改
  const [originalRowData, setOriginalRowData] = useState({});
  // 初始化筛选值为默认的"00",避免undefined
  const [categoryValue, setCategoryValue] = useState("00");
  const [sdlrValue, setSdlrValue] = useState("00");

  // 仅在组件挂载时获取数据
  useEffect(() => {
    axios
      .get("SellerList.json")
      .then(function (response) {
        setOriginalRowData(response.data);
      })
      .catch(function (error) {
        console.log(error);
      });
  }, []);

  // 使用useMemo缓存筛选后的结果,避免每次渲染重复计算
  const filteredRowData = useMemo(() => {
    // 先复制原始数据,避免修改原始对象
    const data = { ...originalRowData };

    Object.keys(data).forEach(rowKey => {
      const row = data[rowKey];
      // 初始默认显示所有行
      let isHidden = false;

      // 分类筛选逻辑
      if (categoryValue !== "00" && row.code !== categoryValue) {
        isHidden = true;
      }

      // SDLR筛选逻辑:如果分类已经隐藏,就不用再判断SDLR;否则判断SDLR条件
      if (!isHidden && sdlrValue !== "00" && row.sdlrId !== sdlrValue.trim()) {
        isHidden = true;
      }

      data[rowKey] = { ...row, isHidden };
    });

    return data;
  }, [originalRowData, categoryValue, sdlrValue]);

  return (
    <div>
      <h1>Seller Deduplicated Request List</h1>
      <table>
        <thead>
          <tr>
            <th></th>
            <th>Code</th>
            <th>Category</th>
            <th>SDRL ID</th>
            <th>Data Requested (Name or Label for request)</th>
            <th>Request Parameters (Date ranges, etc)</th>
            <th>Request Details (Notes to explain request)</th>
            <th>Format (File type or format for request)</th>
          </tr>
          <tr>
            <th></th>
            <th colSpan={2}>
              <select
                value={categoryValue}
                onChange={(event) => setCategoryValue(event.target.value)}
              >
                <option value="00">Filter by Category</option>
                <option value="02">People</option>
                <option value="01">Finance & Accounting</option>
                <option value="04">Purchasing</option>
                <option value="03">Sales</option> {/* 修复重复value问题 */}
              </select>
            </th>
            <th>
              <select
                value={sdlrValue}
                onChange={(event) => setSdlrValue(event.target.value)}
              >
                <option value="00">Filter by SDLR</option>
                <option value="01.02">01.02</option>
                <option value="02.01">02.01</option>
                <option value="04.01">04.01</option> {/* 去除多余空格 */}
                <option value="05.01">05.01</option>
              </select>
            </th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          {Object.keys(filteredRowData).map((rowKey) => (
            <TableRow
              key={rowKey}
              row={filteredRowData[rowKey]}
              setRowData={setOriginalRowData}
              rowData={filteredRowData}
            />
          ))}
        </tbody>
      </table>
    </div>
  );
}

关键修改点说明

  1. 分离原始数据与筛选后数据:新增originalRowData存储接口返回的原始数据,筛选操作基于原始数据进行,避免数据污染。
  2. 使用useMemo合并筛选逻辑:将分类和SDLR的筛选逻辑合并在一处,仅在原始数据或筛选条件变化时重新计算,既解决了逻辑分散的问题,又避免了直接修改state导致的更新延迟。
  3. 初始化筛选值:将categoryValue和sdlrValue初始化为"00",避免初始值为undefined导致的筛选逻辑异常。
  4. 修复选项异常:修正了分类选项重复的value,去除了SDLR选项中的多余空格,避免匹配失败。
  5. 移除冗余useEffect:原来的两个useEffect被替换为useMemo,彻底解决了状态更新不及时和逻辑互相覆盖的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 23:08:15