这是实时示例代码https://codesandbox.io/embed/wonderful-moon-sc9o2
我想实现某种i18n(例如react-i18next)
当我单击“更改语言”按钮时,我希望所有不同组件的翻译都得到更新:
document.getElementById(result).innerHTMl = `For a 4 years college degree with Annual cost: $${annualCost} and Inflation rate: ${inflationRate}`
+ `You have to pay $${totalCost}.`
+ `You need to save ${annualSaving} annually for ${yearsUntilCollege} years.`;
我的钩子中的// Example.js
// t.ui.btn - is a path to string token
// { ui: { btn: 'Change Language' } }
<button>{t.ui.btn}</button>
变量已正确更改,但是该钩子不会将更改传播到应用程序。相反,它将呈现初始lang
值。
您会注意到lang
如何在控制台中接收初始值。
我的钩子怎么了?如何解决?
index.js
lang
Example.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);
useTranslation.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 };
Header.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 };
en.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 };
de.js 翻译
const dict = {
ui: {
btn: "COUNT",
changeLang: "CHANGE LANGUAGE"
},
app: {
title: "Hook Example"
}
};
export { dict };
答案 0 :(得分:1)
每次从组件调用挂钩时,都会初始化挂钩。当您从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 };