将 material UI 弹出窗口分解为高阶组件,并将弹出窗口状态保持在 `hoc` 中

Factoring material UI popover into a higher order component and keep the popover state in the `hoc`

我在此处关注 React material ui 文档:https://mui.com/components/popover/,并且我正在尝试将所有弹出窗口视图和状态逻辑分解为更高阶的组件。文档中的那个在这里:




function BasicPopoverFromDoc(props) {

    const [anchorEl, setAnchorEl] = React.useState(null);

    const handlePopoverOpen = (event) => {
        setAnchorEl(event.currentTarget);
    };

    const handlePopoverClose = () => {
        setAnchorEl(null);
    };

    const open = Boolean(anchorEl);

    return (
        <div>
            <Typography
                aria-owns={open ? 'mouse-over-popover' : undefined}
                aria-haspopup="true"
                onMouseEnter={handlePopoverOpen}
                onMouseLeave={handlePopoverClose}
                style={{color:'white'}}
            >
                Hover with a Popover.
            </Typography>
            <Popover
                id="mouse-over-popover"
                sx={{
                  pointerEvents: 'none',
                }}
                open={open}
                anchorEl={anchorEl}
                anchorOrigin={{
                  vertical: 'bottom',
                  horizontal: 'left',
                }}
                transformOrigin={{
                  vertical: 'top',
                  horizontal: 'left',
                }}
                onClose={handlePopoverClose}
                disableRestoreFocus
            >
                <Typography sx={{ p: 1 }}>I use Popover.</Typography>
            </Popover>
        </div>
    );
}

我将所有状态逻辑提升到一个 hoc 如下,以 <Child/> 作为参数:

function WithPopOver(props){


    const [anchorEl, setAnchorEl] = React.useState(null);

    const handlePopoverOpen = (event) => {
        setAnchorEl(event.currentTarget);
    };

    const handlePopoverClose = () => {
        setAnchorEl(null);
    };

    const open = Boolean(anchorEl);

    const { Child } = props;

    console.log('with Popover: ', open)


    return (
        <div>
            <Child 
                {...props}
                aria-owns={open ? 'mouse-over-popover' : undefined}
                aria-haspopup="true"
                onMouseEnter={handlePopoverOpen}
                onMouseLeave={handlePopoverClose}
            />
            <Popover
                id="mouse-over-popover"
                sx={{
                  pointerEvents: 'none',
                }}
                open={open}
                anchorEl={anchorEl}
                anchorOrigin={{
                  vertical: 'bottom',
                  horizontal: 'left',
                }}
                transformOrigin={{
                  vertical: 'top',
                  horizontal: 'left',
                }}
                onClose={handlePopoverClose}
                disableRestoreFocus
            >
                <Typography sx={{ p: 1 }}>I use Popover.</Typography>
            </Popover>
        </div>
    );
}

但是当我尝试以这种方式使用它时:

function BasicPopover(props){

    return (
        <WithPopOver
            {...props}
            Child={() => <Typography style={{color:'white'}}> wrapped in hoc </Typography>}
        />
    )
}

弹出窗口似乎没有显示。即使我强行将 open 更改为 true,它也拒绝显示。我在这里错过了什么?

您还没有将 Child 属性传递给它的 children,所以 onMouseEnteronMouseLeave 永远不会触发,试试这个:

<WithPopOver
        {...props}
        Child={(props) => <Typography style={{color:'white'}} {...props}> wrapped in hoc </Typography>}
    />