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

MUI DataTables搜索栏无法更新自定义Dropdown列问题求助

MUI DataTables搜索时自定义Dropdown值不随行变化的解决方案

问题描述

我是Next.js和React新手,使用MUI DataTables构建表格,其中Size列采用自定义Dropdown组件,但使用搜索栏筛选行时,Dropdown的值不会随匹配行变化,始终固定为初始行的数值。

问题代码

Table组件代码

"use client";

import Dropdown from './dropdown';
import { Paper } from '@mui/material';
import MUIDataTable from 'mui-datatables';

export default function Table({ }) {
    let sizes = [
        { id_size: 0, size: 'none' },
        { id_size: 1, size: 'XS' },
        { id_size: 2, size: 'S' },
        { id_size: 3, size: 'M' },
        { id_size: 4, size: 'L' },
        { id_size: 5, size: 'XL' },
        { id_size: 6, size: 'XXL' },
        { id_size: 7, size: 'XXXL' }
    ]
    let students = [
        {
            studentId: 1,
            firstName: 'aaaaaa',
            lastName: 'aaaaa',
            email: 'aaaaaa@aaaaaaa.com',
            sizeId: 4,
            campuses: { campusName: 'aaaaaaaaa' }
        },
        {
            studentId: 2,
            firstName: 'bbbbbb',
            lastName: 'bbbbbb',
            email: 'bbbbb@bbbbbbb.com',
            sizeId: 0,
            campuses: { campusName: 'bbbbbbbb' }
        }
    ]

    const columns = ["First Name", "Last Name", "Email", "Size", "Campus"];
    let data = students.map((row) => (
        [
            row.lastName,
            row.firstName,
            row.email,
            <Dropdown id={row.studentId} studentId={row.studentId} initialValue={row.sizeId} sizes={sizes} />,
            row.campuses.campusName
        ]
    ))

    const options = {
        customToolbarSelect: () => { },
        print: 'false',
        rowsPerPage: 100,
        rowsPerPageOptions: [100, 200],
        tableBodyMaxHeight: '75vh',
        tableId: '1',
    };
    return (
        <>
            <br />
            <Paper>
                <MUIDataTable
                    title={"List of Students"}
                    columns={columns}
                    data={data}
                    options={options}
                />
            </Paper>
        </>
    )
}

Dropdown组件代码

"use client";

import MenuItem from '@mui/material/MenuItem';
import Select from '@mui/material/Select';
import FormControl from '@mui/material/FormControl';
import { useState } from 'react';

export default function Dropdown({ id, initialValue, studentId, sizes }) {
    const [currentValue, setCurrentValue] = useState(initialValue);
    console.log(studentId + " " + initialValue + " " + currentValue);

    const handleChange = (event) => {
        // setCurrentValue(event.target.value);
      
    };

    return (
        <>
            <FormControl>
                <Select
                    labelId={id}
                    id={id}
                    value={currentValue}
                    label={id}
                    sx={{ m: 1, minWidth: 120 }}
                    size="small"
                    onChange={handleChange}
                >
                    {sizes.map((size) => (
                        <MenuItem key={size.id_size} value={size.id_size}>{size.size}</MenuItem>
                    ))}
                </Select>
            </FormControl>
        </>
    );
}

问题原因

Dropdown组件用useState(initialValue)初始化状态,但MUI DataTables在搜索筛选时会复用已渲染的组件,不会重新创建。此时initialValue prop已经随匹配行变化,但useState仅在组件首次挂载时读取初始值,后续prop更新不会自动同步到state,导致Dropdown始终显示首次挂载时的初始值。

解决方案

方案1:用useEffect同步prop到state

在Dropdown组件中添加useEffect监听initialValue变化,当prop更新时同步更新state:

"use client";

import MenuItem from '@mui/material/MenuItem';
import Select from '@mui/material/Select';
import FormControl from '@mui/material/FormControl';
import { useState, useEffect } from 'react';

export default function Dropdown({ id, initialValue, studentId, sizes }) {
    const [currentValue, setCurrentValue] = useState(initialValue);

    // 监听initialValue变化,同步更新状态
    useEffect(() => {
        setCurrentValue(initialValue);
    }, [initialValue]);

    const handleChange = (event) => {
        setCurrentValue(event.target.value);
    };

    return (
        <FormControl>
            <Select
                labelId={id}
                id={id}
                value={currentValue}
                label={id}
                sx={{ m: 1, minWidth: 120 }}
                size="small"
                onChange={handleChange}
            >
                {sizes.map((size) => (
                    <MenuItem key={size.id_size} value={size.id_size}>{size.size}</MenuItem>
                ))}
            </Select>
        </FormControl>
    );
}

方案2:直接使用prop作为Select的值(无需本地状态)

如果Dropdown仅需展示对应行的sizeId,不需要用户修改后维护本地状态,可以直接去掉state,用initialValue作为Select的value:

"use client";

import MenuItem from '@mui/material/MenuItem';
import Select from '@mui/material/Select';
import FormControl from '@mui/material/FormControl';

export default function Dropdown({ id, initialValue, studentId, sizes }) {
    const handleChange = (event) => {
        // 这里可添加数据更新逻辑,比如调用接口修改学生尺码
    };

    return (
        <FormControl>
            <Select
                labelId={id}
                id={id}
                value={initialValue}
                label={id}
                sx={{ m: 1, minWidth: 120 }}
                size="small"
                onChange={handleChange}
            >
                {sizes.map((size) => (
                    <MenuItem key={size.id_size} value={size.id_size}>{size.size}</MenuItem>
                ))}
            </Select>
        </FormControl>
    );
}

效果说明

  • 方案1通过useEffect确保每次行数据变化时,Dropdown的状态都会同步更新,既保留了本地修改的能力,又能在搜索筛选时正确显示对应行的数值。
  • 方案2完全依赖父组件传递的initialValue,组件更简洁,适合仅展示或需要联动父组件状态的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:30:04