Добавить класс в тег HTML <body> с помощью React?

Im делает модальный в моем проекте React, который требует добавления класса в тело, когда модаль открыт и удаляется, когда он закрыт.

Я мог бы сделать это старым способом jQuery, запустив javascript, который добавляет/удаляет класс, но это не похоже на обычную философию React.

Должен ли я вместо setState на моем компоненте верхнего уровня сказать, что мода мода открыта или закрыта? Даже если бы я сделал это, так как его отображали в div на странице, он по-прежнему являлся побочным эффектом для редактирования элемента тела, так что есть ли польза для этой дополнительной проводки?

Ответ 1

TL; DR используйте 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 });
}

Ответ 2

С новым React (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>
    );
};

Ответ 3

Как и то, что упоминалось в @brian, попробуйте иметь компонент контейнера верхнего уровня, который обтекает ваши другие компоненты. (предполагая, что вы не используете сокращение в своем приложении)

В этом компоненте верхнего уровня:

  • Добавить логическое состояние (например. modalOpen) для переключения класса CSS
  • Добавьте методы (например. handleOpenModal и handleCloseModal), чтобы изменить логическое состояние.
  • Передайте созданные выше методы как реквизиты в свой <Modal /> компонент