Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | 1x 1x 1x 14x 1x 5x 1x 4x 4x 4x 3x 1x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x | import { useCallback, useEffect, useMemo, useState } from "react";
import { useLocation, useHistory } from "react-router-dom";
import { Language, TEMP_SUPPORTED_LANGUAGES } from "../../constants/languages";
import { QUERY_PARAMS } from "../../constants/url";
import { useQueryParams } from "../../hooks/useQueryParams";
// Only supported language atm
const defaultLang = Language.TypeScript;
const LOCAL_KEY = "preferred-language";
const isValidLang = (lang?: string | Language): lang is Language =>
lang != null && TEMP_SUPPORTED_LANGUAGES.has(lang as Language);
const getInitialLang = (langFromParams: string | Language): Language => {
// First, use language from query params in url
if (isValidLang(langFromParams)) {
return langFromParams;
}
// Next check for one stored in localStorage
try {
const storedLang = (localStorage.getItem(LOCAL_KEY) ?? "") as Language;
if (isValidLang(storedLang)) return storedLang;
} catch {
// Do nothing, we just don't want to crash if localStorage access is blocked.
}
// Otherwise fallback to a default
return defaultLang;
};
export interface UseLanguageOptions {
/**
* Syncs the preferred language to a query param in URL
*/
updateUrl?: boolean;
/**
* Saves the selected language to localStorage on select
*/
updateSaved?: boolean;
}
export const useLanguage = (options: UseLanguageOptions = {}) => {
const { updateUrl, updateSaved } = options;
const { pathname, hash } = useLocation();
const { replace } = useHistory();
const params = useQueryParams();
const langFromParams = params.get(QUERY_PARAMS.LANGUAGE) as Language;
// Passed as function to guarantee it runs on hook mount
const [language, setLanguage] = useState<Language>(() =>
getInitialLang(langFromParams)
);
// State subscribes to query param changes
useEffect(() => {
Iif (isValidLang(langFromParams) && langFromParams !== language) {
setLanguage(langFromParams);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [langFromParams]);
// Syncs language changes to URL if updateUrl = true
useEffect(() => {
Iif (langFromParams !== language && updateUrl) {
params.set(QUERY_PARAMS.LANGUAGE, language);
replace({ pathname, hash, search: params.toString() });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [language, updateUrl]);
const update = useCallback(
(val: Language) => {
setLanguage(val);
if (updateSaved) {
try {
localStorage.setItem(LOCAL_KEY, val);
} catch {
// OK to fail silently
}
}
},
[updateSaved]
);
return useMemo(() => [language, update] as const, [language, update]);
};
|