Next.js项目中点击Select组件外部无法更新isOpen状态如何解决?
解决方案
核心实现逻辑是监听全局点击事件,判断点击区域是否在Select组件外,若组件处于展开状态且点击区域在外部,则主动更新isOpen状态为false。
代码修改
1. 修改Select组件
新增外部点击监听逻辑,代码如下:
import React, { useRef, useEffect } from 'react'; import PropTypes from 'prop-types'; const Select = props => { // 绑定Select外层容器,用于判断点击区域范围 const selectWrapperRef = useRef(null); useEffect(() => { const handleOutsideClick = (event) => { // 点击区域不在组件内部且当前下拉为展开状态时,触发关闭 if (selectWrapperRef.current && !selectWrapperRef.current.contains(event.target) && props.isOpen) { props.onClose?.(); } } // 绑定全局鼠标按下事件 document.addEventListener('mousedown', handleOutsideClick); // 组件卸载时移除事件监听,避免内存泄漏 return () => document.removeEventListener('mousedown', handleOutsideClick); }, [props.isOpen, props.onClose]); return ( <div ref={selectWrapperRef}> {props.isOpen ? <div>Select is Opened</div> : <div>Select is closed</div> } <select onClick={props.onClick} name={props.name} id={props.id}> {props.children} </select> </div> ); }; Select.propTypes = { name: PropTypes.string.isRequired, id: PropTypes.string, isOpen: PropTypes.bool, onClick: PropTypes.func, onChange: PropTypes.func, children: PropTypes.node, // 新增关闭回调prop onClose: PropTypes.func }; export default Select;
2. 修改Form组件
新增关闭回调方法,传入Select组件:
import React, {useState} from 'react'; import Select from "./Select"; const Form = props => { const [isOpen, setIsOpen] = useState(false); const onClickHandler = () => { setIsOpen(state => !state); } // 新增关闭逻辑 const onCloseHandler = () => { setIsOpen(false); } return ( <div> <form> <Select isOpen={isOpen} name='select' id='select' onClick={onClickHandler} onClose={onCloseHandler} > <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </Select> </form> </div> ); }; export default Form;
注意事项
- 选用
mousedown而非click事件监听,是为了避免和页面其他阻止冒泡的点击事件冲突,触发逻辑更稳定 - 必须在useEffect的清理函数中移除全局事件监听,否则会造成内存泄漏问题
内容的提问来源于stack exchange,提问作者Ali Ehyaie
相关产品推荐
相关产品推荐

