0

这个主 App 函数有一个自定义钩子,当按钮被点击时会触发:

import React, { useEffect } from 'react';
import { BrowserRouter, Route, Link } from 'react-router-dom'
import HomeScreen from  './Screens/HomeScreen'
import './App.css';
import { useCurrentLang } from './utils/useCurrentLang'
import {strings as engstrings} from './res/lang/eng/strings'

function App() {

  const currentStrings = useCurrentLang(engstrings); 
  return (
    <BrowserRouter>
       <div className="grid-container">
        <header className="header">
          <div className="brand">
            <Link to="/" >
                
            </Link>
          </div>
          <div className="header-side">
            {currentStrings.currentlang.subtitle}
          </div>
          <div className="header-right">
            <button  {...currentStrings}> 
              {currentStrings.currentlang.traduction} 
            </button>
          </div>
          <div>

          </div>
        </header>
        <main className="main">
          <div className="content">
            <Route path="/" exact={true} component={HomeScreen} />
          </div>

        </main>
        <footer className="footer">
          &#169; 2020 
         </footer>
      </div>
    </BrowserRouter>
   
  );
}

export default App;

然而这个从 App 路由的组件函数也需要使用在 App 中找到的钩子对象的相同引用:

import React from 'react';
import terminalImage from '../res/images/GNOMETerminalIcon.png';
import {useCurrentLang} from '../utils/useCurrentLang'
import {strings as engstrings} from '../res/lang/eng/strings'

const { Link } = require("react-router-dom");

function HomeScreen() {
    const currentStrings = useCurrentLang(engstrings); 
    return <div className="home">
        <ul className="menu-list">
            <li>
                <div className="about-link section">
                    <Link to="/about">{currentStrings.currentlang.about}</Link>
                </div>
            </li>
            <li>
                <div className="projects-link section">
                    <Link to="/about">{currentStrings.currentlang.about}</Link>   
                </div>
            </li>
            <li>
                <div className="contacts-link section">
                    <Link to="/about">{currentStrings.currentlang.about}</Link>
                </div>
            </li>
            <li>
                <div className="suggestions-link section">
                    <Link to="/about">{currentStrings.currentlang.about}</Link>   
                </div>
            </li>
        </ul>
        <div className="home-main-image">
            <img src={terminalImage} />
        </div>
    </div>
}

export default HomeScreen;

当 App 上的钩子被触发时,这两个函数是否可以重新渲染?如果是,如何?

编辑:currentLang 钩子:

import {useState} from 'react'
import {strings as frstrings} from '../res/lang/fr/strings'
import {strings as engstrings} from '../res/lang/eng/strings'

export const useCurrentLang = initialState => {
    if(initialState === 0){
        initialState = engstrings
    }
    const [currentlang, setLang] = useState(initialState);
    return {
        currentlang: currentlang,
        onClick: () => {
            if(currentlang === engstrings){
                setLang(frstrings)
            } else {
                setLang(engstrings)
            }
        }
    }
}
4

1 回答 1

3

问题

您面临的主要问题是您的一部分React Tree不知道语言已经改变。

解决方案

使用Language Context为所有 React 树提供更新的 a 并将其包装在应用程序的顶部。用外行的话来说,现在你的应用程序在任何lang变化时都处于监听模式。所以基本上,React 现在所做的就是每当lang发生变化时,它会lang从上下文中找到使用的任何地方并更新组件。

此处有关 React 上下文的文档

import React from 'react'
// import {strings as frstrings} from '../res/lang/fr/strings'
// import {strings as engstrings} from '../res/lang/eng/strings'

const lang = {
  // in this way, you could dynamically add lang
  // later on which worrying about if-elses in your component
  en: {
    hello: 'hello'
  },
  fr: {
    hello: 'bonjour',
  },
}

const langDict = (key) => lang[key]

const LanguageContext = React.createContext(null);

function LanguageProvider({ initialState = 'en', children }) {
  const [lang, setLang] = React.useState(initialState);

  return (
    <LanguageContext.Provider value={[langDict(lang), setLang]}>
      {children}
    </LanguageContext.Provider>
  )
}

function useLanguage() {
  return React.useContext(LanguageContext);
}

export default function AppWrapper() {
  return (
    <LanguageProvider>
        <App />
    </LanguageProvider>
  )
}

function App() {
  const [lang, setLang] = useLanguage();

  return (
    <div>
      <h1>{lang.hello}</h1>
      <button onClick={() => setLang('fr')}>French</button>
      <button onClick={() => setLang('en')}>English</button>
    </div>
  )
}

于 2020-09-01T03:00:51.763 回答