I have a small localization provider library that makes calls to a server to get translations based on the user's selected language. I've omitted a few helper functions for brevity. Here is the gist of it:
const LocaleContext = createContext();
const LocaleProvider = ({ children }) => {
const [state, setState] = useState(defaultValues);
if (state.phrases === null) {
changeLanguage(defaultLanguage);
}
return (
<LocaleContext.Provider value={[state, setState]}>
{children}
</LocaleContext.Provider>
);
};
const changeLanguage = (lang) => {
const [state, setState] = useContext(LocaleContext);
fetch(localizationEndpointForThatLanguage)
.then(response => response.json())
.then(data => {
setState({ ...state, phrases: data });
};
const translateString = (string) => {
const [state] = useContext(LocaleContext);
// if the string argument is found in state, return the translated value;
}
export { LocaleContext, LocaleProvider, changeLanguage, translateString };
Here is the component that uses it:
const Home = () => {
const [state, setState] = useContext(SiteContext);
useEffect(() => {
state.fetchContent(opts, state, setState);
}, []);
return (
<div>
{state.data && state.data.map((datum) => <div>{datum.title}</div>)}
<div onClick={() => changeLanguage('pl_PL')}>Change to Polish</div>
<div>{changeLanguage('Translate me')}</div>
</div>
);
};
The code gives me the error "TypeError: Cannot read property '0' of undefined" when trying to destructure the LocaleContext in the changeLanguage function. It works fine for the translateString function. It works if I manually pass state into the changeLanguage function.
const Home = () => {
const [state, setState] = useContext(SiteContext);
const [locale, setLocale] = useContext(LocaleContext);
useEffect(() => {
state.fetchContent(opts, state, setState);
}, []);
return (
<div>
{state.data && state.data.map((datum) => <div>{datum.title}</div>)}
<div onClick={() => changeLanguage('pl_PL')}>Change to Polish</div>
<div>{changeLanguage('Translate me', locale, setLocale)}</div>
</div>
);
};
and
const changeLanguage = (lang, state, setState) => {
fetch(localizationEndpointForThatLanguage)
.then(response => response.json())
.then(data => {
setState({ ...state, phrases: data });
});
};
I am fine with having to handoff context values throughout the app to make things work. I'd like help understanding why my translateString function does not require me to pass context values to it.