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
相关产品推荐
相关产品推荐

