我正在尝试使用我编写的该组件:
import React from 'react';
import MenuItem from '@material-ui/core/MenuItem';
import ListItemText from '@material-ui/core/ListItemText';
const ITEMS = {
item1: { id: 1, name: '1', description: 'item1', protected: true },
item2: { id: 2, name: '2', description: 'item2' },
item3: { id: 3, name: '3', description: 'item3' },
}
// See https://github.com/DefinitelyTyped/DefinitelyTyped/issues/20356#issuecomment-435708501
// for an explanation on why the component return type was cast to `any` below.
const MenuItemList: any = () => {
return Object.values(ITEMS).map(
(item) =>
!item.protected && (
<MenuItem key={item.id} value={item.id}>
<ListItemText
primary={item.name}
secondary={item.description}
/>
</MenuItem>
)
);
};
export default MenuItemList;
...一次在类型Textfield
的{{1}}内,另一次在select
组件内。但是,在浏览器中访问它时出现以下错误:
Menu
关于如何解决此问题的任何想法?
更新:
这是我称呼此组件的方式:
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
<Menu
id={id}
open={open}
anchorEl={anchorEl}
getContentAnchorEl={null}
keepMounted={false}
onClose={handleClose}
elevation={2}
PaperProps={{
square: true,
}}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'right',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
>
< MenuItemList />
</Menu>
更新2
这是错误堆栈:
<Field
name="items"
label="Select Item"
padding={2}
component={TextField}
select
fullWidth
SelectProps={{
MenuProps: {
elevation: 2,
getContentAnchorEl: null,
anchorOrigin: {
vertical: 'bottom',
horizontal: 'left',
},
transformOrigin: {
vertical: 'top',
horizontal: 'left',
},
},
IconComponent: ExpandMoreIcon,
}}
variant="filled"
InputProps={{
disableUnderline: true,
}}
>
<MenuItemList />
</Field>
答案 0 :(得分:1)
似乎问题不在此组件上。您可以在使用MenuItemList
的地方粘贴组件的代码吗?在Material-ui使用的ref react上似乎是个问题
我还建议使用filter
[doc]来过滤受保护的项目。
import React from 'react';
import MenuItem from '@material-ui/core/MenuItem';
import ListItemText from '@material-ui/core/ListItemText';
const ITEMS = {
item1: { id: 1, name: '1', description: 'item1', protected: true },
item2: { id: 2, name: '2', description: 'item2' },
item3: { id: 3, name: '3', description: 'item3' },
}
const MenuItemList: any = () => {
return Object.values(ITEMS).filter(item => !item.protected).map(
(item) =>
<MenuItem key={item.id} value={item.id}>
<ListItemText
primary={item.name}
secondary={item.description}
/>
</MenuItem>
);
};
export default MenuItemList;
修改
菜单使用菜单的第一个子项作为菜单内部使用的Popover组件的“内容锚”。 “内容锚点”是Popover尝试与锚点元素(菜单外部的元素,该元素是用于放置菜单的参考点)对齐的菜单中的DOM元素。
为了利用第一个孩子作为内容锚点,Menu向其添加了一个引用(使用cloneElement)。为了避免收到您收到的错误(并使定位正常工作),功能组件需要将ref转发到它提供的组件之一(通常是最外面的组件-在您的情况下为div)。
将div用作Menu的直接子代时,不会出现错误,因为div可以成功接收到引用。
因此,您应该将MenuItemList
的代码更改为:
import React from 'react';
import MenuItem from '@material-ui/core/MenuItem';
import ListItemText from '@material-ui/core/ListItemText';
const ITEMS = {
item1: { id: 1, name: '1', description: 'item1', protected: true },
item2: { id: 2, name: '2', description: 'item2' },
item3: { id: 3, name: '3', description: 'item3' },
}
const MenuItemList: any = () => {
return (
<div>
{Object.values(ITEMS)
.filter(item => !item.protected)
.map(item => (
<MenuItem key={item.id} value={item.id}>
<ListItemText primary={item.name} secondary={item.description} />
</MenuItem>
))}
</div>
);
};
export default MenuItemList;
答案 1 :(得分:1)
stefano.orlando的解释似乎是正确的,直到他们提出解决方案为止。将div包裹在其他组件周围不会导致引用被转发。为此,您需要使用React.forwardRef。以下代码将使之成为参考,如果将引用传递到MenuItemList
,则该引用将被重定向到MenuItem
内部的第一个MenuItemList
:
import React from 'react';
import MenuItem from '@material-ui/core/MenuItem';
import ListItemText from '@material-ui/core/ListItemText';
const ITEMS = {
item1: { id: 1, name: '1', description: 'item1', protected: true },
item2: { id: 2, name: '2', description: 'item2' },
item3: { id: 3, name: '3', description: 'item3' },
}
const MenuItemList: any = React.ForwardRef((props, ref) => {
return (
Object.values(ITEMS)
.filter(item => !item.protected)
.map((item, index) => (
<MenuItem
ref={index === 0 ? ref : undefined}
key={item.id}
value={item.id}
>
<ListItemText primary={item.name} secondary={item.description} />
</MenuItem>
))
);
});
export default MenuItemList;