Skip to content

Toggle - React/NextJS 13 (with hot fix) #30

@Biratus

Description

@Biratus

Hello,

I just started using DaisyUI and tailwindcss. I want to say first and foremost that I am not an expert (with these libraries).
None of the examples or answers worked for me so I checked the code to see what is going on. And I want to share my findings and my solution.

The themeChange(false) did nothing so I investigated and put the themeToggle function in my useEffect and especially the last part.
I added a return function to the useEffect to unsubscribe, with React 18 the listener is called twice so the toggle is useless (i.e. changes theme and reverts back to the initial one => No visual change on the page).

And that is all actually.

Here is my toggle component (I am using react-feather for icons):

"use client";
import { useEffect } from "react";
import { Moon, Sun } from "react-feather";

export default function SwitchTheme({}) {
    
  useEffect(() => {
    [...document.querySelectorAll("[data-toggle-theme]")].forEach((el) => {
      el.addEventListener("click", toggleTheme);
    });

    return () =>
      [...document.querySelectorAll("[data-toggle-theme]")].forEach((el) =>
        el.removeEventListener("click", toggleTheme)
      );
  }, []);

  return (
    <div className="flex gap-2">
      <Sun />
      <input
        type="checkbox"
        className="toggle"
        data-toggle-theme="light,dark"
      />
      <Moon />
    </div>
  );
}

function toggleTheme(evt: any) {
  var themesList = evt.target.getAttribute("data-toggle-theme");
  if (themesList) {
    var themesArray = themesList.split(",");
    if (document.documentElement.getAttribute("data-theme") == themesArray[0]) {
      if (themesArray.length == 1) {
        document.documentElement.removeAttribute("data-theme");
        localStorage.removeItem("theme");
      } else {
        document.documentElement.setAttribute("data-theme", themesArray[1]);
        localStorage.setItem("theme", themesArray[1]);
      }
    } else {
      document.documentElement.setAttribute("data-theme", themesArray[0]);
      localStorage.setItem("theme", themesArray[0]);
    }
  }
}

tailwind.config.js if needed:

module.exports = {
  content: [
    "./app/**/*.{js,ts,jsx,tsx}",
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",

    // Or if using `src` directory:
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [require("daisyui")],
  darkMode: ["class", '[data-theme="dark"]'],
  daisyui: {
    themes: ["light", "dark"],
  },
};

This is a hot fix for the problem I had. As I said I am in no way an expert with these libraries, just wanted to share so you guys could try and implement this in a nice way :) The BIG problem is regarding useEffect and React 18 that calls it twice I think.

Keep me updated if I have done blasphemous stuff with this code... I might take a look in the futur but it works for now..
Cheers !

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions