Выпадающее меню открывается автоматически при загрузке страницы в компоненте React с использованием DaisyUI.

Вопрос или проблема

Я работаю над компонентом React, который позволяет пользователям менять тему моего приложения с помощью выпадающего меню DaisyUI. Выбранная тема сохраняется в localStorage, чтобы сохранять её при обновлении страницы. Однако, когда страница обновляется, выпадающее меню всегда открыто. Я хочу, чтобы оно было закрыто и открывалось только при нажатии на него.

Вот мой код:

import { useEffect, useState } from "react";

function ChangeTheme() {
const \[selectedTheme, setSelectedTheme\] = useState(
localStorage.getItem("selectedTheme") || "default"
);

useEffect(() =\> {
localStorage.setItem("selectedTheme", selectedTheme);
// Применить выбранную тему
document.documentElement.setAttribute("data-theme", selectedTheme);
}, \[selectedTheme\]);

return (
\<div className="dropdown absolute left-0 top-0 m-3"\>
\<div tabIndex={0} role="button" className="btn m-1"\>
Тема
\<svg
width="12px"
height="12px"
className="inline-block h-2 w-2 fill-current opacity-60"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 2048 2048"
\\\>
\<path d="M1799 349l242 241-1017 1017L7 590l242-241 775 775 775-775z"\>\</path\>
\</svg\>
\</div\>
\<ul
tabIndex={0}
className="dropdown-content bg-base-300 rounded-box z-\[1\] w-52 p-2 shadow-2xl"
\\\>
\<li\>
\<input
type="radio"
name="theme-dropdown"
className="theme-controller btn btn-sm btn-block btn-ghost justify-start"
aria-label="Default"
value="default"
checked={selectedTheme === "default"}
onChange={() =\> setSelectedTheme("default")}
/\>
\</li\>
\<li\>
\<input
type="radio"
name="theme-dropdown"
className="theme-controller btn btn-sm btn-block btn-ghost justify-start"
aria-label="Dark"
value="dark"
checked={selectedTheme === "dark"}
onChange={() =\> setSelectedTheme("dark")}
/\>
\</li\>
\<li\>
\<input
type="radio"
name="theme-dropdown"
className="theme-controller btn btn-sm btn-block btn-ghost justify-start"
aria-label="Coffee"
value="coffee"
checked={selectedTheme === "coffee"}
onChange={() =\> setSelectedTheme("coffee")}
/\>
\</li\>
\</ul\>
\</div\>
);
}

export default ChangeTheme;

Ответ или решение

Для того чтобы решить проблему автоматического открытия выпадающего меню при загрузке страницы в компоненте React с использованием DaisyUI, необходимо внести несколько корректировок в ваш код. Давайте разберем этот вопрос детально, а также предложим решения, которые обеспечат правильное поведение выпадающего меню.

Анализ проблемы

Вы сталкиваетесь с ситуацией, когда выпадающее меню для выбора темы всегда открыто после обновления страницы. Это связано с тем, как DaisyUI обрабатывает состояние видимости своих компонентов, если они не считаются интерактивными элементами с предопределенным состоянием. Вам нужно контролировать открытие меню с помощью состояния в вашем компоненте.

Решение

Создадим локальное состояние для управления видимостью выпадающего меню. Также добавим обработчик событий, который будет переключать это состояние при клике на кнопку вызова меню.

Вот переработанный код компонента:

import { useEffect, useState } from "react";

function ChangeTheme() {
    const [selectedTheme, setSelectedTheme] = useState(
        localStorage.getItem("selectedTheme") || "default"
    );
    const [isOpen, setIsOpen] = useState(false); // Состояние для управления видимостью меню

    useEffect(() => {
        localStorage.setItem("selectedTheme", selectedTheme);
        document.documentElement.setAttribute("data-theme", selectedTheme);
    }, [selectedTheme]);

    const toggleDropdown = () => {
        setIsOpen(!isOpen); // Переключаем состояние меню
    };

    const handleThemeChange = (theme) => {
        setSelectedTheme(theme);
        setIsOpen(false); // Закрываем меню после выбора темы
    };

    return (
        <div className="dropdown absolute left-0 top-0 m-3">
            <div 
                tabIndex={0} 
                role="button" 
                className="btn m-1" 
                onClick={toggleDropdown} // Обработчик клика для открытия/закрытия меню
            >
                Тема
                <svg
                    width="12px"
                    height="12px"
                    className="inline-block h-2 w-2 fill-current opacity-60"
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 2048 2048"
                >
                    <path d="M1799 349l242 241-1017 1017L7 590l242-241 775 775 775-775z"/>
                </svg>
            </div>
            {isOpen && ( // Условный рендеринг для выпадающего меню
                <ul className="dropdown-content bg-base-300 rounded-box z-[1] w-52 p-2 shadow-2xl">
                    <li>
                        <input
                            type="radio"
                            name="theme-dropdown"
                            className="theme-controller btn btn-sm btn-block btn-ghost justify-start"
                            aria-label="Default"
                            value="default"
                            checked={selectedTheme === "default"}
                            onChange={() => handleThemeChange("default")}
                        />
                    </li>
                    <li>
                        <input
                            type="radio"
                            name="theme-dropdown"
                            className="theme-controller btn btn-sm btn-block btn-ghost justify-start"
                            aria-label="Dark"
                            value="dark"
                            checked={selectedTheme === "dark"}
                            onChange={() => handleThemeChange("dark")}
                        />
                    </li>
                    <li>
                        <input
                            type="radio"
                            name="theme-dropdown"
                            className="theme-controller btn btn-sm btn-block btn-ghost justify-start"
                            aria-label="Coffee"
                            value="coffee"
                            checked={selectedTheme === "coffee"}
                            onChange={() => handleThemeChange("coffee")}
                        />
                    </li>
                </ul>
            )}
        </div>
    );
}

export default ChangeTheme;

Объяснение изменений

  1. Состояние видимости меню: Мы добавили состояние isOpen, которое управляет открытием и закрытием выпадающего меню.

  2. Обработчик кликов: Функция toggleDropdown используется для переключения состояния видимости меню при клике на кнопку.

  3. Закрытие меню после выбора темы: При выборе темы с помощью функции handleThemeChange, мы не только обновляем selectedTheme, но и закрываем меню.

  4. Условный рендеринг: Мы добавили условное отображение меню ul только в том случае, если isOpen истинно.

Заключение

С помощью указанных изменений ваш компонент будет вести себя корректно, не открывая выпадающее меню автоматически при загрузке страницы. Кроме того, пользователь сможет удобно выбирать тему, а ваша реализация обеспечит хорошую интерактивность. Это решение соответствует современным требованиям разработки на React и позволяет для поддержания чистоты и читаемости кода.

Оцените материал
Добавить комментарий

Капча загружается...