Material UI两个TextField的Popper互斥关闭功能实现问题
问题描述
我现在并排实现了两个TextField组件,它们的end adornment位置都设置了按钮,点击这些按钮可以切换对应Popper的显隐状态。同时每个Popper都绑定了ClickAwayListener,实现点击Popper外部区域时自动关闭Popper的效果。
我的需求是:当第一个Popper处于打开状态时,点击第二个TextField的adornment按钮,需要自动关闭第一个Popper。
遇到的问题
我在end adornment的按钮点击事件中调用了stopPropagation阻止事件冒泡,避免点击按钮时触发ClickAwayListener导致Popper刚打开就立刻关闭,但这也导致点击另一个TextField的按钮时,已打开的Popper无法接收到点击外部的事件,不会自动关闭。
我尝试过把TextField包裹在ClickAwayListener内部,但没有生效。
补充说明
两个TextField是由独立的组件渲染的,我不希望在它们之间传递任何props,要保证组件的独立性。
原始代码
const [firstPopperVisible, setFirstPopperVisible] = React.useState(false); const [secondPopperVisible, setSecondPopperVisible] = React.useState(false); const firstTextFieldRef = React.useRef(); const secondTextFieldRef = React.useRef(); const toggleFirstPopperVisible = (e) => { e.stopPropagation(); setFirstPopperVisible((prev) => !prev); }; const handleFirstPopperClickAway = (e) => { setFirstPopperVisible(false); }; const toggleSecondPopperVisible = (e) => { e.stopPropagation(); setSecondPopperVisible((prev) => !prev); }; const handleSecondPoppertClickAway = (e) => { setSecondPopperVisible(false); }; return ( <div style={{ display: "flex", flexDirection: "row" }}> <div> <TextField label="Outlined" variant="outlined" inputRef={firstTextFieldRef} InputProps={{ endAdornment: ( <InputAdornment position="end"> <IconButton aria-label="toggle password visibility" edge="end" onClick={toggleFirstPopperVisible} > <Visibility /> </IconButton> </InputAdornment> ) }} /> <ClickAwayListener onClickAway={handleFirstPopperClickAway}> <Popper open={firstPopperVisible} anchorEl={firstTextFieldRef.current} placement="bottom-start" > Content </Popper> </ClickAwayListener> </div> <div> <TextField label="Outlined" variant="outlined" inputRef={secondTextFieldRef} InputProps={{ endAdornment: ( <InputAdornment position="end"> <IconButton aria-label="toggle password visibility" edge="end" onClick={toggleSecondPopperVisible} > <Visibility /> </IconButton> </InputAdornment> ) }} /> <ClickAwayListener onClickAway={handleSecondPoppertClickAway}> <Popper open={secondPopperVisible} anchorEl={secondTextFieldRef.current} placement="bottom-start" > Content </Popper> </ClickAwayListener> </div> </div> ); }
临时解决方案
我找到了一个临时解决方案,把TextField包裹在div中,再把这个div包裹在ClickAwayListener内部,同时在需要的Popper自身上阻止事件冒泡。这个方案并不完美,但符合我的业务需求。
<ClickAwayListener onClickAway={handleFirstPopperClickAway}> <div style={{display: inline-box}> <TextField> ..... </TextField> </div> </ClickawayListener> <Popper> .... </Popper>
内容的提问来源于stack exchange,提问作者Andyally
相关产品推荐
相关产品推荐

