Heyo. Working with react and I've encountered a puzzling issue.
import { useState } from "react";
function useTheme() {
const [themeName, setThemeName] = useState("dark");
return [themeName, setThemeName];
}
function Other() {
const [themeName, setThemeName] = useTheme();
return <div>{themeName}</div>;
}
function ThemeSwitcher() {
const [themeName, setThemeName] = useTheme();
return (
<>
<button
onClick={() => {
themeName == "dark" ? setThemeName("light") : setThemeName("dark");
}}
>
{"BUTTON"}
</button>
{themeName}
</>
);
}
function App() {
const [themeName, setPalette] = useTheme();
return (
<div>
<ThemeSwitcher />
<Other />
<div>{themeName}</div>
</div>
);
}
export default App;
This is an extremely basic version of my issue, I've removed everything I could think of and still it persists. I have a an app with a hook called useTheme, that provides a function that changes the name of a state variable "themeName".
I have a button component ThemeSwitcher that, on click, switches the name of the theme between "dark" and "light".
When clicking the button, the themeName state variable updates (which I know for sure, as the {themeName} fragment inside ThemeSwitcher properly updates). However, the {themeName} inside App and the {themeName} inside Other do not actually update. I fail to see the difference here, and I'm currently baffled as to why one would update and not the others.
Any idea why the App component isn't rerendered despite the state variable changing?
They're completely separate states. This:
function useTheme() {
const [themeName, setThemeName] = useState("dark");
return [themeName, setThemeName];
}
is effectively no different from using useState
itself. So your issue is similar to asking why, here:
function Other() {
const [themeName, setThemeName] = useState();
return <div>{themeName}</div>;
}
function ThemeSwitcher() {
const [themeName, setThemeName] = useState();
// ...
the two themeNames
are not in sync - it's because they have no connection to each other.
To fix this, there are usually 2 approaches that can be used:
function App() {
const [themeName, setThemeName] = useTheme();
return (
<div>
<ThemeSwitcher {...{ themeName, setThemeName }} />
<Other {...{ themeName, setThemeName }} />
<div>{themeName}</div>
</div>
);
}