React Material-UI 菜单锚因 react-window 重新渲染而丢失
React Material-UI menu anchor lost because of re-rendered by react-window
我正在为 Material-UI 中 react-window. In the list, every item has an icon button 的用户构建一个无限加载列表,以便进一步操作。
但是我无法将菜单安装在图标附近,因为在为要打开的菜单设置 anchorEl
时会重新呈现图标按钮。 gif 剪辑:
问题与 but has more HOC. The code is listed here. I wish I could use my codesandbox相关,用于演示,但react-measure
的高度一直在增长。
function App() {
const [anchorEl, setAnchorEl] = useState(null);
const openMenu = React.useCallback(e => {
e.stopPropagation();
setAnchorEl(e.currentTarget);
console.log("target", e.currentTarget);
}, []);
const handleClose = () => {
setAnchorEl(null);
};
const [items, setItems] = React.useState([]);
const isItemLoaded = index => {
const c = index < items.length;
// console.log("isItemLoaded", index, c);
return c;
};
const loadMoreItems = (startIndex, stopIndex) => {
console.log("loadMoreItems", startIndex, items);
setItems(items.concat(Array(10).fill({ name: "1", size: startIndex })));
};
const innerET = React.forwardRef((props, ref) => (
<div ref={ref} {...props} />
));
const Row = React.useCallback(
({ index, style }) => {
console.log("Row", items, index);
return items[index] ? (
<ListItem style={style} key={index}>
<Button variant="contained" color="primary" onClick={openMenu}>
Row {index}: {items[index].size}
</Button>
</ListItem>
) : null;
},
[items, openMenu]
);
const innerListType = React.forwardRef((props, ref) => (
<List ref={ref} {...props} />
));
return (
<div className="App">
<div className="ceiling">Something at top</div>
<div className="interest">
<Menu anchorEl={anchorEl} onClose={handleClose} />
<Measure bounds offset>
{({ measureRef, contentRect }) => {
const height = Math.min(
contentRect && contentRect.offset
? document.getElementById("root").getBoundingClientRect()
.height - contentRect.offset.top
: itemSize * items.length,
itemSize * items.length
);
console.log(
"bounds",
height,
contentRect.bounds,
contentRect.offset
);
return (
<div>
<div />
<div ref={measureRef} className="measurement">
<InfiniteLoader
isItemLoaded={isItemLoaded}
itemCount={itemCount}
loadMoreItems={loadMoreItems}
>
{({ onItemsRendered, ref }) => (
<FixedSizeList
height={height}
width={
contentRect.bounds !== undefined &&
contentRect.bounds.width !== undefined
? contentRect.bounds.width
: -1
}
itemCount={itemCount}
itemSize={itemSize}
onItemsRendered={onItemsRendered}
ref={ref}
innerElementType={innerET}
>
{Row}
</FixedSizeList>
)}
</InfiniteLoader>
</div>
</div>
);
}}
</Measure>
</div>
</div>
);
}
据我了解,涟漪效应会在第一次点击时触发方框内的重新渲染。此外,点击重新渲染后的第二次点击不会触发重新渲染。这对我来说更奇怪。
编辑:我修复了第一个沙箱。通过使用 Material UI 的列表,这个问题是可以重现的。 https://codesandbox.io/s/blissful-butterfly-qn3g7
所以问题出在使用innerElementType
属性.
原来需要一个钩子
const innerListType = React.useMemo(() => {
return React.forwardRef((props, ref) => (
<List component="div" ref={ref} {...props} />
));
}, []);
为了解决我的问题,需要更仔细地处理用于处理事件的钩子。
我正在为 Material-UI 中 react-window. In the list, every item has an icon button 的用户构建一个无限加载列表,以便进一步操作。
但是我无法将菜单安装在图标附近,因为在为要打开的菜单设置 anchorEl
时会重新呈现图标按钮。 gif 剪辑:
问题与react-measure
的高度一直在增长。
function App() {
const [anchorEl, setAnchorEl] = useState(null);
const openMenu = React.useCallback(e => {
e.stopPropagation();
setAnchorEl(e.currentTarget);
console.log("target", e.currentTarget);
}, []);
const handleClose = () => {
setAnchorEl(null);
};
const [items, setItems] = React.useState([]);
const isItemLoaded = index => {
const c = index < items.length;
// console.log("isItemLoaded", index, c);
return c;
};
const loadMoreItems = (startIndex, stopIndex) => {
console.log("loadMoreItems", startIndex, items);
setItems(items.concat(Array(10).fill({ name: "1", size: startIndex })));
};
const innerET = React.forwardRef((props, ref) => (
<div ref={ref} {...props} />
));
const Row = React.useCallback(
({ index, style }) => {
console.log("Row", items, index);
return items[index] ? (
<ListItem style={style} key={index}>
<Button variant="contained" color="primary" onClick={openMenu}>
Row {index}: {items[index].size}
</Button>
</ListItem>
) : null;
},
[items, openMenu]
);
const innerListType = React.forwardRef((props, ref) => (
<List ref={ref} {...props} />
));
return (
<div className="App">
<div className="ceiling">Something at top</div>
<div className="interest">
<Menu anchorEl={anchorEl} onClose={handleClose} />
<Measure bounds offset>
{({ measureRef, contentRect }) => {
const height = Math.min(
contentRect && contentRect.offset
? document.getElementById("root").getBoundingClientRect()
.height - contentRect.offset.top
: itemSize * items.length,
itemSize * items.length
);
console.log(
"bounds",
height,
contentRect.bounds,
contentRect.offset
);
return (
<div>
<div />
<div ref={measureRef} className="measurement">
<InfiniteLoader
isItemLoaded={isItemLoaded}
itemCount={itemCount}
loadMoreItems={loadMoreItems}
>
{({ onItemsRendered, ref }) => (
<FixedSizeList
height={height}
width={
contentRect.bounds !== undefined &&
contentRect.bounds.width !== undefined
? contentRect.bounds.width
: -1
}
itemCount={itemCount}
itemSize={itemSize}
onItemsRendered={onItemsRendered}
ref={ref}
innerElementType={innerET}
>
{Row}
</FixedSizeList>
)}
</InfiniteLoader>
</div>
</div>
);
}}
</Measure>
</div>
</div>
);
}
据我了解,涟漪效应会在第一次点击时触发方框内的重新渲染。此外,点击重新渲染后的第二次点击不会触发重新渲染。这对我来说更奇怪。
编辑:我修复了第一个沙箱。通过使用 Material UI 的列表,这个问题是可以重现的。 https://codesandbox.io/s/blissful-butterfly-qn3g7
所以问题出在使用innerElementType
属性.
原来需要一个钩子
const innerListType = React.useMemo(() => {
return React.forwardRef((props, ref) => (
<List component="div" ref={ref} {...props} />
));
}, []);
为了解决我的问题,需要更仔细地处理用于处理事件的钩子。