使用 React 向 HTML < body > 标记添加一个类?

我在我的 React 项目中创建了一个模式,它要求在模式打开时将一个类添加到主体中,在模式关闭时将其移除。

我可以通过运行一些普通的 JavaScript 来做到这一点,这些 JavaScript 会添加/删除一个类,但是这并不像正常的 React 哲学。

我是否应该在顶级组件上设置 setState 来判断模态是打开的还是关闭的?即使我这样做了,因为它呈现在页面的 div 中,编辑 body 元素仍然是一个副作用,所以这种额外的连接有什么好处吗?

84814 次浏览

像@brian 提到的那样,尝试使用一个顶级容器组件来包装其他组件。(假设您的应用程序中没有使用 redux)

在这个顶级组件中:

  1. 添加一个布尔状态(例如 modalOpen)来切换 CSS 类
  2. 添加方法(例如 handleOpenModalhandleCloseModal)来修改布尔状态。
  3. 将上面创建的作为道具的方法传递到 <Modal />组件中

ReactJS 有一个正式的 ReactModal 组件,我只需要使用它: https://github.com/reactjs/react-modal

使用 document.body.classList.adddocument.body.classList.remove

我将有两个函数来切换一个状态片段,以显示/隐藏外部组件中的模态。

在这些函数中,我将使用 document.body.classList.adddocument.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

const [isOpen, setIsOpen] = useState(false)
useEffect(() => {
document.body.classList.toggle('modal-open', isOpen);
},[isOpen])
    

<button onCLick={()=> setIsOpen(!isOpen)}>Toggle Modal</button>