如何使用useContext翻译不同的页面

How to use useContext to translate different pages

我正在尝试理解 'useContext' 以翻译我的应用程序的不同组件。在我的代码中,我收到错误“未定义语言、语言和 handleIdiom”。我知道在我的“菜单”组件中我没有定义它们,但是在“语言”组件中它是我的提供者,我定义了所有。

我想因为我的“菜单”是用 包装的,所以我可以使用它。另外,能否请您查看代码并告诉我哪里出了问题以及需要进行哪些更改才能实现我的目标?

上下文:

import React, { createContext, useState, useContext } from "react";

export const languages = {
  en: {
    about: "about",
    project: "project",
    contact: "contact",
    slogan: "Think the Design, and I design the Code.",
    button: "Learn more",
  },
  ptbr: {
    about: "sobre",
    project: "projetos",
    contact: "contatos",
    slogan: "Think the Design, and I design the Code.",
    button: "Learn more",
  },
  jp: {
    about: "nihon",
    project: "nihon",
    contact: "nihon",
    slogan: "nihon",
    button: "nihon",
  },
  ru: {
    about: "руский",
    project: "руский",
    contact: "руский",
    slogan: "руский",
    button: "руский",
  },
};

export const LanguagesContext = React.createContext({ languages });

function Language() {
  const [idiom, setIdiom] = useState("en");

  const handleIdiom = (language) => (e) => {
    setIdiom(language);
  };

  return (
    <LanguagesContext.Provider
      value={{ idiom, setIdiom }}
    ></LanguagesContext.Provider>
  );
}

export function useIdiom() {
  const context = useContext(LanguagesContext);
  const { idiom, setIdiom } = context;
  return { idiom, setIdiom };
}

export default Language;

菜单:

import React, { useState, useContext } from "react";
import "./MenuStyle.scss";
import { FaBars } from "react-icons/fa";
import br from "../../assets/menu/brazil.svg";
import en from "../../assets/menu/eua.svg";
import ru from "../../assets/menu/russia.svg";
import jp from "../../assets/menu/japan.svg";

import { useIdiom } from "../../provider/Language.jsx";

import LanguagesProvider from "../../provider/Language";

function Menu() {
  // burger menu
  const [click, setClick] = useState(false);
  const handleClick = () => setClick(!click);
  const Close = () => setClick(false);

  // tradution
  const idiom = useIdiom();

  return (
    <LanguagesProvider>
      <div>
        <div
          className={click ? "main-container" : ""}
          onClick={() => Close()}
        />

        <nav className="navbar" onClick={(e) => e.stopPropagation()}>
          <div className="nav-container">
            <div exact to="/" className="nav-logo">
              <h1>Flávio</h1>
            </div>

            <div className="links">
              <ul className={click ? "nav-menu active" : "nav-menu"}>
                <li className="nav-item">
                  <a href="" activeClassName="active" className="nav-links">
                    {languages[language].about}
                  </a>
                </li>
                <li className="nav-item">
                  <a href="" activeClassName="active" className="nav-links">
                    {languages[language].project}
                  </a>
                </li>
                <li className="nav-item">
                  <a href="" activeClassName="active" className="nav-links">
                    {languages[language].contact}
                  </a>
                </li>

                <div className="flags-desktop">
                  <li>
                    <img src={en} alt="en" onClick={handleIdiom("en")} />
                  </li>
                  <li>
                    <img src={br} alt="ptbr" onClick={handleIdiom("ptbr")} />
                  </li>
                  <li>
                    <img src={ru} alt="ru" />
                  </li>
                  <li>
                    <img src={jp} alt="jp" />
                  </li>
                </div>
              </ul>
            </div>

            <div className="flags">
              <img src={en} alt="en" />
              <img src={br} alt="ptbr" />
              <img src={ru} alt="ru" />
              <img src={jp} alt="jp" />
            </div>

            <div className="nav-icon" onClick={handleClick}>
              <i className={click ? "fa fa-times" : "fa fa-bars"}>
                <FaBars />
              </i>
            </div>
          </div>
        </nav>
      </div>
    </LanguagesProvider>
  );
}

export default Menu;

我们应该在我们希望访问 Context.Provider 语言的地方包装组件。然后我们可以使用 hook useContext 访问上下文。还添加了将所选语言保存到 localStorage 的逻辑。可以这样做:

import React, { useState, useContext } from "react";

// App.js

const defaultLanguage = "br";
export const LanguageContext = React.createContext();

function App() {
  const [language, setLanguage] = useState(() => {
    const langFromLocalStorage = window.localStorage.getItem("lang");

    return langFromLocalStorage ? langFromLocalStorage : defaultLanguage;
  });

  React.useEffect(() => {
    window.localStorage.setItem("lang", language);
  }, [language]);

  return (
    <div className="App">
      <LanguageContext.Provider value={[language, setLanguage]}>
        <Menu />
        <HomeComponent />
      </LanguageContext.Provider>
    </div>
  );
}

export default App;

// Menu.js :
// import { LanguageContext } from "...";

function Menu() {
  const languages = {
    en: {
      about: "about",
      project: "project",
      contact: "contact",
      slogan: "Think the Design, and I design the Code.",
      button: "Learn more",
    },
    br: {
      about: "sobre",
      project: "projetos",
      contact: "contatos",
      slogan: "Think the Design, and I design the Code.",
      button: "Learn more",
    },
    jp: {
      about: "nihon",
      project: "nihon",
      contact: "nihon",
      slogan: "nihon",
      button: "nihon",
    },
    ru: {
      about: "руский",
      project: "руский",
      contact: "руский",
      slogan: "руский",
      button: "руский",
    },
  };

  const [click, setClick] = useState(false);
  const Close = () => setClick(false);

  const [language, setLanguage] = useContext(LanguageContext);
  console.log(`language`, language);

  return (
    <>
      <div>
        <div
          className={click ? "main-container" : ""}
          onClick={() => Close()}
        />

        <nav className="navbar" onClick={(e) => e.stopPropagation()}>
          <div className="nav-container">
            <div className="links">
              <h1>Current Language is: {language}</h1>
              <ul className={click ? "nav-menu active" : "nav-menu"}>
                <li className="nav-item">
                  <a href="" activeClassName="active" className="nav-links">
                    {languages[language].about}
                  </a>
                </li>
                <li className="nav-item">
                  <a href="" activeClassName="active" className="nav-links">
                    {languages[language].project}
                  </a>
                </li>
                <li className="nav-item">
                  <a href="" activeClassName="active" className="nav-links">
                    {languages[language].contact}
                  </a>
                </li>

                <div className="flags-desktop">
                  <li>
                    <img
                      src={"en"}
                      alt="en"
                      onClick={() => setLanguage("en")}
                    />
                  </li>
                  <li>
                    <img
                      src={"br"}
                      alt="ptbr"
                      onClick={() => setLanguage("br")}
                    />
                  </li>
                  <li>
                    <img
                      src={"ru"}
                      alt="ru"
                      onClick={() => setLanguage("ru")}
                    />
                  </li>
                  <li>
                    <img
                      src={"jp"}
                      alt="jp"
                      onClick={() => setLanguage("jp")}
                    />
                  </li>
                </div>
              </ul>
            </div>
          </div>
        </nav>
      </div>
    </>
  );
}

const HomeComponent = () => {
  const [language] = useContext(LanguageContext);
  console.log(`language`, language);

  return (
    <div>
      <h1>HomeComponent</h1>
      <h1>Current Language is: {language}</h1>
    </div>
  );
};