使用 React 将 class 添加到 HTML <body> 标签?
Add a class to the HTML <body> tag with React?
我正在我的 React 项目中创建一个模态框,该模态框需要 class 在模态框打开时添加到正文并在它关闭时删除。
我可以通过 运行 一些香草 JavaScript 的旧 jQuery 方式来添加/删除 class,但这感觉不像正常React 哲学。
我应该改为在我的顶级组件上设置状态来说明模式是打开还是关闭?即使我这样做了,因为它被渲染到页面上的 div 中,编辑 body 元素仍然是一个副作用,所以这个额外的连接有什么好处吗?
就像@brian 提到的那样,尝试使用一个顶级容器组件来包裹您的其他组件。 (假设您没有在您的应用中使用 redux)
在此顶级组件中:
- 添加布尔状态(例如
modalOpen
)以切换 CSS class
- 添加方法(例如
handleOpenModal
& handleCloseModal
)来修改布尔状态。
- 将上面创建的方法作为 props 传递到您的
<Modal />
组件中
ReactJS 有一个官方的 React Modal 组件,我会使用它:https://github.com/reactjs/react-modal
TL;DR 使用 document.body.classList.add
和 document.body.classList.remove
我有两个函数可以将一个状态切换到 show/hide 外部组件中的模态。
在这些函数中,我会使用 document.body.classList.add
和 document.body.classList.remove
方法来操纵主体 class,具体取决于模态的状态,如下所示:
openModal = (event) => {
document.body.classList.add('modal-open');
this.setState({ showModal: true });
}
hideModal = (event) => {
document.body.classList.remove('modal-open');
this.setState({ showModal: false });
}
有了新的 React (16.8),这可以用 hooks 解决:
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>
);
};
实际上你不需要打开和关闭2个函数,你可以使用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>
我正在我的 React 项目中创建一个模态框,该模态框需要 class 在模态框打开时添加到正文并在它关闭时删除。
我可以通过 运行 一些香草 JavaScript 的旧 jQuery 方式来添加/删除 class,但这感觉不像正常React 哲学。
我应该改为在我的顶级组件上设置状态来说明模式是打开还是关闭?即使我这样做了,因为它被渲染到页面上的 div 中,编辑 body 元素仍然是一个副作用,所以这个额外的连接有什么好处吗?
就像@brian 提到的那样,尝试使用一个顶级容器组件来包裹您的其他组件。 (假设您没有在您的应用中使用 redux)
在此顶级组件中:
- 添加布尔状态(例如
modalOpen
)以切换 CSS class - 添加方法(例如
handleOpenModal
&handleCloseModal
)来修改布尔状态。 - 将上面创建的方法作为 props 传递到您的
<Modal />
组件中
ReactJS 有一个官方的 React Modal 组件,我会使用它:https://github.com/reactjs/react-modal
TL;DR 使用 document.body.classList.add
和 document.body.classList.remove
我有两个函数可以将一个状态切换到 show/hide 外部组件中的模态。
在这些函数中,我会使用 document.body.classList.add
和 document.body.classList.remove
方法来操纵主体 class,具体取决于模态的状态,如下所示:
openModal = (event) => {
document.body.classList.add('modal-open');
this.setState({ showModal: true });
}
hideModal = (event) => {
document.body.classList.remove('modal-open');
this.setState({ showModal: false });
}
有了新的 React (16.8),这可以用 hooks 解决:
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>
);
};
实际上你不需要打开和关闭2个函数,你可以使用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>