为什么从Local Storage获取新值时,带条件运算符的className不更新?
问题:LocalStorage 更新后组件未重新渲染
我把菜单展开状态存在 LocalStorage 里,写了getItem和setItem操作函数,还实现了自定义 Hook useMenu管理状态,但点击触发toggleMenu后,LocalStorage 里的值明明已经更新,菜单的 className 却没变化,组件也完全不重新渲染。
相关代码如下:
自定义 Hook 实现
const getItem = (key, defaultValue) => { // 获取项,若为undefined/null则返回默认值 }; const setItem = (key, value) => { // 设置项,功能正常 }; export const useMenu = () => { const isOpened = Boolean(getItem("isOpened", true)); const toggleMenu = useCallback(() => { setItem("isOpened", !isOpened); }, [isOpened]); // ... return { isOpened, toggleMenu, }; };
组件中使用
const { isOpened, toggleMenu } = useMenu();
<div className={isOpened ? styles.openedContainer : styles.closedContainer}>
原因分析
isOpened是直接从 LocalStorage 读取的普通变量,不是 React 的状态变量(比如useState返回的状态)。React 只有在状态或 props 变化时才会触发组件重渲染,所以哪怕 LocalStorage 里的值变了,isOpened也不会自动更新,组件自然不会重新渲染。
解决方案
用useState来管理isOpened状态,初始化时从 LocalStorage 取值,同时在toggleMenu里同步更新状态和 LocalStorage:
修正后的useMenu Hook
const getItem = (key, defaultValue) => { const storedValue = localStorage.getItem(key); return storedValue !== null ? JSON.parse(storedValue) : defaultValue; }; const setItem = (key, value) => { localStorage.setItem(key, JSON.stringify(value)); }; export const useMenu = () => { // 初始化时从LocalStorage取状态,初始化函数仅执行一次 const [isOpened, setIsOpened] = useState(() => { return Boolean(getItem("isOpened", true)); }); const toggleMenu = useCallback(() => { setIsOpened(prevState => { const newState = !prevState; // 同步更新LocalStorage setItem("isOpened", newState); return newState; }); }, []); return { isOpened, toggleMenu, }; };
关键改动说明
- 用
useState定义isOpened状态,确保状态变化能触发组件重渲染 - 采用函数式更新
setIsOpened,避免依赖外部isOpened变量,同时保证获取到最新的状态值 useCallback依赖数组为空,减少不必要的回调重新创建
修改后,点击触发toggleMenu时,isOpened状态会更新,React 会自动触发组件重渲染,菜单的 className 也会随之切换,LocalStorage 的值也能保持同步。
内容的提问来源于stack exchange,提问作者iwishyoujoy
相关产品推荐
相关产品推荐

