Reputation: 29
I am trying to update my components but they will not update when a new value is updated in my LocalStorage.
Here is my code:
App.js:
import './App.css';
import CTA from './components/CTA';
function App() {
return (
<div className="App">
<CTA />
</div>
);
}
export default App;
The component im having issues with:
The component is looking at localStorage for language selection which is true or false if true, english else, french
But the dom is not updating automatically? It changes when I refresh though...
Kinda a noob...
CTA.js
import * as React from 'react';
import CTA_Image from '../assets/cibc-event.jpeg'
import styles from '../styles/language.module.css'
import useLocalStorage from '../util/store'
import LanguageButtons from './LanguageButtons'
export default function CTA(props) {
const [isEnglish] = useLocalStorage('isEnglish', true);
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 />
</>
)
}
LanguageButton.js:
import { Button } from "@mui/material"
import useLocalStorage from '../util/store'
import styles from '../styles/language.module.css'
const LanguageButtons = () => {
const [isEnglish, setEnglish] = useLocalStorage('isEnglish', true);
let handleLanguage = (props) => {
setEnglish(props)
// console.log(isEnglish)
}
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
This is handling the Language Change of course.
store.js - useLocalStorage handling
import {useState} from 'react';
// Hook
function useLocalStorage(key, initialValue) {
// State to store our value
// Pass initial state function to useState so logic is only executed once
const [storedValue, setStoredValue] = useState(() => {
if (typeof window === "undefined") {
return initialValue;
}
try {
// Get from local storage by key
const item = window.localStorage.getItem(key);
// Parse stored json or if none return initialValue
return item ? JSON.parse(item) : initialValue;
} catch (error) {
// If error also return initialValue
console.log(error);
return initialValue;
}
});
// Return a wrapped version of useState's setter function that ...
// ... persists the new value to localStorage.
const setValue = (value) => {
try {
// Allow value to be a function so we have same API as useState
const valueToStore =
value instanceof Function ? value(storedValue) : value;
// Save state
setStoredValue(valueToStore);
// Save to local storage
if (typeof window !== "undefined") {
window.localStorage.setItem(key, JSON.stringify(valueToStore));
}
} catch (error) {
// A more advanced implementation would handle the error case
console.log(error);
}
};
return [storedValue, setValue];
}
export default useLocalStorage;
Any help is appreciated thanks! Apologies for noob question
Upvotes: 0
Views: 613
Reputation: 370759
The different components' calls to useLocalStorage
are not linked. So, calling a state setter in one of them won't result in the other one seeing its state change as well.
Call useLocalStorage
only once, in a parent component - lift state up. Then, pass down the state value and the state setter to whatever needs it.
export default function CTA(props) {
const [isEnglish, setEnglish] = useLocalStorage('isEnglish', true);
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 {...{ setEnglish }}/>
</>
);
}
and then use the new props:
const LanguageButtons = ({ setEnglish }) => (
<>
<Button variant="contained" className={styles.languageButton} onClick={()=>setEnglish(true)}>English</Button>
<Button variant="contained" className={styles.languageButton} onClick={()=>setEnglish(false)}>French</Button>
</>
);
Upvotes: 1