这是实时示例代码 https://codesandbox.io/embed/wonderful-moon-sc9o2
我想实现一种 i18n(如 react-i18next(
当我单击"更改语言"按钮时,我希望我在不同组件中的所有翻译都已更新:
// Example.js
// t.ui.btn - is a path to string token
// { ui: { btn: 'Change Language' } }
<button>{t.ui.btn}</button>
我的钩子中的lang
变量已更改,但钩子不会将更改传播到应用程序。相反,它呈现初始lang
值。
您可以注意到lang
如何在控制台中接收初始值。
我的钩子有什么问题?如何解决?
索引.js
import React from "react";
import ReactDOM from "react-dom";
import { Example } from "./Example";
import { Header } from "./Header";
import { useTranslation } from "./useTranslation";
import "./styles.css";
function App() {
const { t } = useTranslation();
return (
<div className="App">
<Header />
<h3>{t.app.title}</h3>
<div>
<Example />
</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
示例.js
import React, { useState } from "react";
import { useTranslation } from "./useTranslation";
function Example() {
const [count, setCount] = useState({ count: 1 });
const { t } = useTranslation();
function onClick(ev) {
setCount(prevState => ({
count: ++prevState.count
}));
}
return (
<div>
<p>Clicks state: {JSON.stringify(count)}</p>
<button onClick={onClick}>{t.ui.btn}</button>
</div>
);
}
export { Example };
使用翻译.js钩
子import React, { useState, useEffect } from "react";
import { dict as en } from "./en";
import { dict as de } from "./de";
const useTranslation = () => {
const [lang, setLang] = useState("en");
const dict = {
en,
de
};
function changeLang(lang) {
console.log("[useTranslation][changeLang] lang", lang);
setLang(lang);
}
console.log("[useTranslation] lang", lang);
return {
t: dict[lang],
changeLang: changeLang,
lang
};
};
export { useTranslation };
标题.js
import React, { useState } from "react";
import { useTranslation } from "./useTranslation";
function Header() {
const { changeLang, lang, t } = useTranslation();
function onChangeLang(ev) {
console.log("[index][onChangeLang] lang", lang);
changeLang(lang === "en" ? "de" : "en");
}
return (
<div>
<button onClick={onChangeLang}>{t.ui.changeLang}</button>
<span>{lang}</span>
</div>
);
}
export { Header };
英文.js翻译
const dict = {
ui: {
btn: "COUNT",
changeLang: "CHANGE LANGUAGE"
},
app: {
title: "Hook Example"
}
};
export { dict };
德.js翻译
const dict = {
ui: {
btn: "Anzahl",
changeLang: "SPRACHE ÄNDERN"
},
app: {
title: "Hook-Beispiel"
}
};
export { dict };
每次从组件调用钩子时,钩子都会初始化。当您从Header
调用同一个钩子并App
正在创建状态的两个独立实例时lang
。相反,你需要的是 React Context,它可以跨组件保留状态。
const LanguageContext = createContext({
lang: "en",
setLang: () => {},
});
const LanguageProvider = ({ children }) => {
const [lang, setLang] = useState("en");
return (
<LanguageContext.Provider value={{ lang, setLang }}>
{children}
</LanguageContext.Provider>
)
}
const useTranslation = () => {
const langContext = useContext(LanguageContext);
const dict = {
en,
de
};
return {
t: dict[langContext.lang],
lang: langContext.lang,
changeLang: langContext.setLang,
};
};
export { useTranslation, LanguageContext, LanguageProvider };
代码沙盒 |反应上下文