大意:我有一个菜单,我想在本地存储器中存储指示菜单打开的变量。
首先,我编写了获取和设置LocalStorage变量的函数:
const getItem = (key, defaultValue) => {
// getting item, if undefined/null return defaultValue
};
const setItem = (key, value) => {
// just setting item, works perfect
};
字符串
然后我实现了自定义钩子,在那里我使用这些函数。代码看起来像这样:
export const useMenu = () => {
const isOpened = Boolean(getItem("isOpened", true));
const toggleMenu = useCallback(() => {
setItem("isOpened", !isOpened);
}, [isOpened]);
// ...
return {
isOpened,
toggleMenu,
};
};
型
移动到带有组件的主文件。我用钩子获取变量:
const { isOpened, toggleMenu } = useMenu();
型
然后在主容器中,我有className的条件运算符:
<div className={isOpened ? styles.openedContainer : styles.closedContainer}>
型
在容器内,我通过单击切换变量:
<div onClick={toggleMenu}>
型
主要的问题是我的菜单没有关闭!这意味着className没有改变。但同时onClick事件工作得很好,因为我可以在浏览器的控制台中看到isOpened变量会及时改变。有什么原因会发生这种情况吗?
- 关于localStorage类型:是的,我知道在localStorage中你只能存储字符串。当我从localStorage中获取一个项目时,我将其转换为布尔类型。我在控制台中检查了typeof isOpened,它似乎是一个布尔值。*
const { useCallback } = React;
const fakeStorage = new Map();
const styles = {
openedContainer: "opened",
closedContainer: "closed",
};
const getItem = (key, defaultValue) => {
const value = fakeStorage.get(key);
// Sadly, Stack Snippets with transpiling enabled don't understand
// nullish coalescing, have to go old-school
if (typeof value === "undefined") {
return defaultValue;
}
return value;
};
const setItem = (key, value) => {
fakeStorage.set(key, value);
};
/*export*/ const useMenu = () => {
const isOpened = Boolean(getItem("isOpened", true));
const toggleMenu = useCallback(() => {
setItem("isOpened", !isOpened);
}, [isOpened]);
// ...
return {
isOpened,
toggleMenu,
};
};
const Example = () => {
const { isOpened, toggleMenu } = useMenu();
return (
<div className={isOpened ? styles.openedContainer : styles.closedContainer}>
<div onClick={toggleMenu}>toggle</div>
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
.opened {
color: green;
}
.closed {
color: red;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
1条答案
按热度按时间kcugc4gi1#
问题是,这个变化并没有改变React用来知道何时重新渲染组件的任何东西。它超出了React所知道的范围。
你可以通过将它保持在一个state成员中来将它带入React所知道的事情中;这里有一个内置
useState
的例子:字符串
有很多方法可以实现这一点。这里,我将本地存储与状态变量并行。您也可以通过
useEffect
驱动状态变量(并使用回调来更新状态,以避免使用isOpened
作为useCallback
的依赖项);型