我在我的 React 项目中创建了一个模式,它要求在模式打开时将一个类添加到主体中,在模式关闭时将其移除。
我可以通过运行一些普通的 JavaScript 来做到这一点,这些 JavaScript 会添加/删除一个类,但是这并不像正常的 React 哲学。
我是否应该在顶级组件上设置 setState 来判断模态是打开的还是关闭的?即使我这样做了,因为它呈现在页面的 div 中,编辑 body 元素仍然是一个副作用,所以这种额外的连接有什么好处吗?
像@brian 提到的那样,尝试使用一个顶级容器组件来包装其他组件。(假设您的应用程序中没有使用 redux)
在这个顶级组件中:
modalOpen
handleOpenModal
handleCloseModal
<Modal />
ReactJS 有一个正式的 ReactModal 组件,我只需要使用它: https://github.com/reactjs/react-modal
使用 document.body.classList.add和 document.body.classList.remove
document.body.classList.add
document.body.classList.remove
我将有两个函数来切换一个状态片段,以显示/隐藏外部组件中的模态。
在这些函数中,我将使用 document.body.classList.add和 document.body.classList.remove方法来操作依赖于模态状态的主体类,如下所示:
openModal = (event) => { document.body.classList.add('modal-open'); this.setState({ showModal: true }); } hideModal = (event) => { document.body.classList.remove('modal-open'); this.setState({ showModal: false }); }
使用新的反应(16.8) ,这个问题可以用 钩子解决:
import {useEffect} from 'react'; const addBodyClass = className => document.body.classList.add(className); const removeBodyClass = className => document.body.classList.remove(className); export default function useBodyClass(className) { useEffect( () => { // Set up className instanceof Array ? className.map(addBodyClass) : addBodyClass(className); // Clean up return () => { className instanceof Array ? className.map(removeBodyClass) : removeBodyClass(className); }; }, [className] ); }
然后,在组件中
export const Sidebar = ({position = 'left', children}) => { useBodyClass(`page--sidebar-${position}`); return ( <aside className="..."> {children} </aside> ); };
实际上,打开和关闭不需要两个函数,可以使用 document.body.classList.toggle
document.body.classList.toggle
const [isOpen, setIsOpen] = useState(false) useEffect(() => { document.body.classList.toggle('modal-open', isOpen); },[isOpen]) <button onCLick={()=> setIsOpen(!isOpen)}>Toggle Modal</button>