React函数组件状态变更时DOM不更新问题求助
问题原因
你当前的问题是CTA和LanguageButtons组件各自维护了独立的isEnglish状态:虽然两个组件都从localStorage读取同一份数据,但它们的state是完全分开的。当LanguageButtons调用setEnglish更新localStorage时,CTA组件里的isEnglish state并不会自动刷新——因为你写的useLocalStorage钩子只在组件初始化时读取一次localStorage,之后不会监听localStorage的变化。
方案一:状态提升(最简单,适合新手)
把语言状态提到父组件(App.js),通过props传递给子组件,让两个组件共享同一个状态,状态变化时所有依赖组件都会自动更新。
修改步骤:
- App.js:把
useLocalStorage的状态放在这里,作为全局共享状态
import './App.css'; import CTA from './components/CTA'; import useLocalStorage from './util/store'; function App() { const [isEnglish, setIsEnglish] = useLocalStorage('isEnglish', true); return ( <div className="App"> <CTA isEnglish={isEnglish} setIsEnglish={setIsEnglish} /> </div> ); } export default App;
- CTA.js:不再自己调用
useLocalStorage,直接接收父组件传递的状态
import * as React from 'react'; import CTA_Image from '../assets/cibc-event.jpeg' import styles from '../styles/language.module.css' import LanguageButtons from './LanguageButtons' export default function CTA({ isEnglish, setIsEnglish }) { React.useEffect(() => { console.log(isEnglish) }, [isEnglish]) console.log(isEnglish) return ( <> <img src={CTA_Image} className={styles.ctaImage} alt='' /> {isEnglish === true ? <p className={styles.ctaBody}> English, i am english, yes </p> : <p className={styles.ctaBody}> French, parle french, oui </p> } <LanguageButtons setIsEnglish={setIsEnglish} /> </> ) }
- LanguageButtons.js:同样接收父组件的
setIsEnglish,不再自己维护状态
import { Button } from "@mui/material" import styles from '../styles/language.module.css' const LanguageButtons = ({ setIsEnglish }) => { let handleLanguage = (value) => { setIsEnglish(value) } return ( <> <Button variant="contained" className={styles.languageButton} onClick={()=>handleLanguage(true)}>English</Button> <Button variant="contained" className={styles.languageButton} onClick={()=>handleLanguage(false)}>French</Button> </> ) } export default LanguageButtons
方案二:改进useLocalStorage钩子(通用型,适合多组件共享)
如果后续有更多组件需要用到语言状态,不想每次都传props,可以修改useLocalStorage钩子,让它监听storage事件,自动同步localStorage的变化。
修改store.js:
import { useState, useEffect } from 'react'; function useLocalStorage(key, initialValue) { const [storedValue, setStoredValue] = useState(() => { if (typeof window === "undefined") { return initialValue; } try { const item = window.localStorage.getItem(key); return item ? JSON.parse(item) : initialValue; } catch (error) { console.log(error); return initialValue; } }); // 监听storage事件,同步其他组件/标签页修改的localStorage值 useEffect(() => { const handleStorageChange = (e) => { if (e.key === key) { try { setStoredValue(e.newValue ? JSON.parse(e.newValue) : initialValue); } catch (error) { console.log(error); setStoredValue(initialValue); } } }; window.addEventListener('storage', handleStorageChange); return () => window.removeEventListener('storage', handleStorageChange); }, [key, initialValue]); const setValue = (value) => { try { const valueToStore = value instanceof Function ? value(storedValue) : value; setStoredValue(valueToStore); if (typeof window !== "undefined") { window.localStorage.setItem(key, JSON.stringify(valueToStore)); // 手动触发storage事件(同一标签页修改localStorage不会自动触发) window.dispatchEvent(new StorageEvent('storage', { key: key, newValue: JSON.stringify(valueToStore) })); } } catch (error) { console.log(error); } }; return [storedValue, setValue]; } export default useLocalStorage;
修改后,你原来的CTA和LanguageButtons组件不需要做任何改动,就能实现状态同步更新。
内容的提问来源于stack exchange,提问作者emartindev
相关产品推荐
相关产品推荐

