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

Material UI Table行筛选异常问题排查求助

搜索功能问题排查:控制台输出匹配行但表格无变化,赋值结果后TextField只读

问题描述

在TextField中执行搜索时,匹配的行能在控制台正确输出,但表格完全没有变化。尝试将搜索结果赋值给新数组后,TextField变为只读状态,恳请协助排查该问题。


现有代码

状态设置与数据获取函数

const [rows, setRows]: any = useState([]);
const [checked, setChecked]: any = useState(false); 
const [selected, setSelected] = React.useState<readonly string[]>([]);

useEffect(() => {
    if (!checked) {
        setChecked(true);
        fetchData();
    }
}, [checked]);

const fetchData: any = async () => {
    const response: any = await axios.get(`/api/layer_data`);
    setChecked(true);
    let dataRows: any[] = response.data;
    dataRows.map((dataRow: any) => (dataRow.isSelected = false));
    console.log('response: ', response.data);
    setRows(dataRows);
};

数据筛选handleSearch函数

const handleSearch = (e: any) => {
    const inputSearch = e.target.value;
    rows.filter((row: any) => {
        if (inputSearch == '') {
            return rows;
        } else if (row.product_id == inputSearch) {
            console.log(row);
            return row;
        } else if (row.sku_id == inputSearch) {
            console.log(row);
            return row;
        } else if (row.description == inputSearch) {
            console.log(row);
            return row;
        } else if (row.units_per_layer == inputSearch) {
            console.log(row);
            return row;
        } else if (row.in_stock == inputSearch) {
            console.log(row);
            return row;
        } else if (row.bin == inputSearch) {
            console.log(row);
            return row;
        }
    });
};

TextField定义

<TextField
    onChange={(e) => handleSearch(e)}
    label="Search..."
    fullWidth
    variant="outlined"
    className={style.padding_right}
/>

表格渲染映射函数

{rows.sort(getComparator(order, orderBy)).map((row: any, index: any) => {
    const isItemSelected = isSelected(row.product_id);
    const labelId = `enhanced-table-checkbox-${index}`;

    return (
        <StyledTableRow
            hover
            onClick={(event) => handleClick(event, row.product_id)}
            role="checkbox"
            aria-checked={isItemSelected}
            tabIndex={-1}
            key={row.product_id}
            selected={isItemSelected}
        >
            <StyledTableCell padding="checkbox">
                <Checkbox
                    color="primary"
                    checked={row.isSelected}
                    inputProps={{
                        'aria-labelledby': labelId
                    }}
                    onChange={handleCheckbox}
                    value={index}
                />
            </StyledTableCell>
            <StyledTableCell align="right">
                <input
                    type="number"
                    min="0"
                    required
                    defaultValue="0"
                    onChange={(e) => handleInput(e, index)}
                />
            </StyledTableCell>
            <StyledTableCell align="right">{row.sku_id}</StyledTableCell>

            <StyledTableCell component="th" id={labelId} scope="row" padding="none" align="right">
                {row.product_id}
            </StyledTableCell>
            <StyledTableCell align="right">{row.in_stock}</StyledTableCell>
            <StyledTableCell align="right">{row.bin}</StyledTableCell>
            <StyledTableCell align="right">{row.units_per_layer}</StyledTableCell>
            <StyledTableCell align="right">{row.description}</StyledTableCell>
        </StyledTableRow>
    );
})}

问题排查与修复

核心问题分析

  1. 表格无变化:handleSearch中仅执行了filter操作,但未将过滤结果通过setRows更新状态,React无法感知数据变化,因此表格不会重新渲染。同时filter回调返回值逻辑错误(应返回布尔值而非数组/对象)。
  2. TextField变只读:若直接用过滤结果覆盖rows状态,会丢失原始数据。当输入清空时,无法恢复完整数据集,导致后续搜索无数据可过滤,表现为TextField"只读"。

修复步骤

1. 新增状态存储原始数据

添加originalRows状态保存接口返回的完整数据,确保过滤始终基于原始数据集操作:

const [rows, setRows]: any = useState([]);
const [originalRows, setOriginalRows]: any = useState([]); // 新增状态
const [checked, setChecked]: any = useState(false); 
const [selected, setSelected] = React.useState<readonly string[]>([]);

const fetchData: any = async () => {
    const response: any = await axios.get(`/api/layer_data`);
    setChecked(true);
    let dataRows: any[] = response.data;
    dataRows.map((dataRow: any) => (dataRow.isSelected = false));
    console.log('response: ', response.data);
    setRows(dataRows);
    setOriginalRows(dataRows); // 保存原始数据
};

2. 重写handleSearch函数

修正过滤逻辑,更新状态并支持清空输入恢复原始数据:

const handleSearch = (e: any) => {
    const inputSearch = e.target.value.trim();
    // 清空输入时恢复原始数据
    if (!inputSearch) {
        setRows(originalRows);
        return;
    }
    // 基于原始数据过滤,返回布尔值判断匹配
    const filteredRows = originalRows.filter((row: any) => {
        return row.product_id === inputSearch ||
               row.sku_id === inputSearch ||
               row.description === inputSearch ||
               row.units_per_layer === inputSearch ||
               row.in_stock === inputSearch ||
               row.bin === inputSearch;
    });
    console.log(filteredRows);
    setRows(filteredRows); // 更新状态触发表格渲染
};

3. 优化表格排序逻辑

rows.sort()会直接修改原数组(违反React状态不可变原则),需先复制数组再排序:

{[...rows].sort(getComparator(order, orderBy)).map((row: any, index: any) => {
    // 原渲染逻辑保持不变
})}

额外建议

  • 避免使用any类型,给状态和函数定义明确的TypeScript类型,减少潜在错误。
  • 若需要模糊搜索,可将匹配逻辑改为row.product_id.includes(inputSearch),并统一转小写避免大小写敏感问题。
  • 数据量较大时,用useMemo缓存过滤结果,减少不必要的重渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 13:48:22