在MUI DataGridPro/DataGridPremium表头渲染Select时触发onBlur错误
当在<DataGridPro />或<DataGridPremium />的列头中渲染<Select />组件时,切换选项功能正常,但焦点离开Select组件时会抛出以下错误:
Failed to execute 'contains' on 'Node': parameter 1 is not of type 'Node'.
TypeError: Failed to execute 'contains' on 'Node': parameter 1 is not of type 'Node'.
用户的代码示例如下:
return ( ... <DataGridPro ... columns={[ ... renderHeader: () => ( <FormControl> <InputLabel>Choose Me</InputLabel> <Select label="Choose Me" size="small" onChange={setItem} > <MenuItem value="Option 1">Option 1</MenuItem> <MenuItem value="Option 2">Option 2</MenuItem> </Select> </FormControl> ), ]} /> ... );
问题原因
这个错误源于DataGrid的列头焦点处理逻辑:当焦点离开列头内的元素时,网格会尝试检查焦点目标节点是否属于网格内部。但MUI Select的下拉菜单默认通过Portal挂载在body层级,而非列头容器内,导致DataGrid拿到的节点不符合contains方法的参数要求,从而触发错误。
解决方案
方案一:阻止Select的onBlur事件冒泡
给Select组件添加onBlur事件处理函数,阻止事件向上冒泡到DataGrid的列头容器,避免网格执行错误的焦点检查逻辑。
修改后的代码:
renderHeader: () => ( <FormControl> <InputLabel>Choose Me</InputLabel> <Select label="Choose Me" size="small" onChange={setItem} onBlur={(e) => e.stopPropagation()} > <MenuItem value="Option 1">Option 1</MenuItem> <MenuItem value="Option 2">Option 2</MenuItem> </Select> </FormControl> ),
方案二:禁用Select的Portal渲染
通过MenuProps={{ disablePortal: true }}让Select的下拉菜单直接挂载在Select的父元素下,而非body层级。这样DataGrid的焦点检查逻辑能正确识别节点,不会触发错误。
修改后的代码:
renderHeader: () => ( <FormControl> <InputLabel>Choose Me</InputLabel> <Select label="Choose Me" size="small" onChange={setItem} MenuProps={{ disablePortal: true }} > <MenuItem value="Option 1">Option 1</MenuItem> <MenuItem value="Option 2">Option 2</MenuItem> </Select> </FormControl> ),
方案对比
- 方案一操作简单,不改变DOM结构,适合大多数场景;但如果需要DataGrid处理列头的其他焦点相关逻辑,可能会有影响。
- 方案二能保持DataGrid焦点逻辑的完整性,但下拉菜单的样式可能受列头容器的overflow等样式限制,需要额外调整CSS适配。
内容的提问来源于stack exchange,提问作者TheScrappyDev
相关产品推荐
相关产品推荐

