使用 React Hooks 和 Context API 更改语言

Posted

技术标签:

【中文标题】使用 React Hooks 和 Context API 更改语言【英文标题】:Changing language with React Hooks and Contex API 【发布时间】:2021-06-25 05:25:35 【问题描述】:

我正在创建一个页面,它可以使用 3 种语言。我创建了 3 个文件,其中包含更改显示文本所需的数据。这个概念是检查用户浏览器语言并相应地显示语言(它工作正常),但也让用户选择通过按钮更改页面的语言(它不起作用)。我使用 Context API 来传递语言和函数来将语言更改为其他组件 - 传递语言有效,但传递函数没有。问题是当我点击按钮时页面没有响应,当它像这样传递时:

changeToPl: changeToPl,

在文章中使用了这种方式:https://medium.com/swlh/react-context-api-hooks-and-functional-state-7c9005b43432

但如果我这样做:

changeToPl: changeToPl(),

我有太多的渲染。包含上下文和语言逻辑的 App 组件下方:

const LanguageContext = React.createContext(
    // language: '',
    // changeLanguage: () => ,
  
);

const App = () => 

  let detectedLanguage = '';

  if (navigator.language.includes('pl')) 
    detectedLanguage = pl;
   else if (navigator.language.includes('de')) 
    detectedLanguage = de;
   else 
    detectedLanguage = en;
  

  const [userLanguage, setUserLanguage] = useState(detectedLanguage);

  /*const chooseLanguage = (lang) => 
    // setUserLanguage(en);
    localStorage.setItem('lang', 'eeen');
    console.log(lang);
  */
  
  const changeToPl = () => 
    setUserLanguage(pl);
    console.log('pl');
  

  const changeToEn = () => 
    setUserLanguage(en);
    console.log('en');
  

  const changeToDe = () => 
    setUserLanguage(de);
    console.log('de');
  

  // let chosenLanguage = userLanguage;

  const usedLanguage = userLanguage || detectedLanguage;


  return (
    <LanguageContext.Provider 
      value=
        language: usedLanguage,
        changeToPl: changeToPl,
        changeToEn: changeToEn,
        changeToDe: changeToDe,
      
    >
      <GlobalStyle />
      <CookieBanner />
      <PopUp />
      <Navbar />
      /* <Sidebar /> */
      <Switch>
        <Route exact path='/' component=Home /> 
        <Route exact path='/artworks/:slug' component=Artwork />
        <Route exact path='/exhibitions' component=ExhibitionList />
        <Route exact path='/biography' component=Biography />
        <Route exact path='/contact' component=Contact />
        <Route component=Error />
      </Switch>
    </LanguageContext.Provider>
  );



export App, LanguageContext;

以及包含用于更改语言的按钮的侧边栏组件:

export const Sidebar = (position, hideSidebar) => 

  const usedLanguage = useContext(LanguageContext);

  return (
    <>
      <Route exact path='/artworks/:slug'> /* DISPLAYED ONLY IN ARTWORK COMPONENT */
        <Link to='/'>
          <BackButton>
            usedLanguage.language.menu.backToMainPage
          </BackButton>
        </Link>
      </Route>
      <Sidenav style=right: position>
        <Link to='/' onClick=hideSidebar>
          <Button text=usedLanguage.language.menu.artworksMenuButton color=variables.DIMGRAY/>
        </Link>
        <Link to='/exhibitions' onClick=hideSidebar>
          <Button text=usedLanguage.language.menu.exhibitionsMenuButton color=variables.DIMGRAY/>
        </Link>
        <Link to='/biography' onClick=hideSidebar>
          <Button text=usedLanguage.language.menu.biographyMenuButton color=variables.DIMGRAY/>
        </Link>
        <Link to='/contact' onClick=hideSidebar>
          <Button text=usedLanguage.language.menu.contactMenuButton color=variables.DIMGRAY/>
        </Link>
        <LanguageButtonsWrapper>
      <Button text='pl' color=variables.DIMGRAY onClick=LanguageContext.changeToPl />
      <Button text='en' color=variables.DIMGRAY onClick=LanguageContext.changeToEn />
      <Button text='de' color=variables.DIMGRAY onClick=LanguageContext.changeToDe />
    </LanguageButtonsWrapper>
        <SocialButtons>
          <SocialButtonIcon href='https://www.facebook.com/StructuralistArt/'>
            <AiFillFacebook />
          </SocialButtonIcon>
          <SocialButtonIcon href='https://www.instagram.com/structuralist_art/'>
            <AiFillInstagram />
          </SocialButtonIcon>
          <SocialButtonIcon href='https://www.behance.net/michalkrol263a63?fbclid=IwAR1LWaRyvVuh9UuM3MHByTYgqDOKG8Qo7h6mQq7tTM3ezJXU-HQ4Wtq09i8'>
            <AiFillBehanceSquare />
          </SocialButtonIcon>
        </SocialButtons>
      </Sidenav>
    </>
  )

我知道用于更改语言的函数可能更通用(3 合 1),上下文数据可能在单独的文件中,我必须使用 localStorage,但现在我想处理所描述的问题。

【问题讨论】:

【参考方案1】:

好的,我想通了。问题是我的应用程序的结构和顺便说一句。我之前问过的事情:) 因为我想构建可重复使用的按钮,所以它看起来像这样:

export const Button = (text, color, clickHandler) => 

  return (
    <AppButton onClick=clickHandler style=color: color>
      text
    </AppButton>
  );
;

因此我需要像这样传递 changeToPl/changeToEn/changeToDe 函数:

<Button text='pl' color=variables.DIMGRAY clickHandler=usedLanguage.changeToPl />

不是这样的:

<Button text='pl' color=variables.DIMGRAY onClick=usedLanguage.changeToPl />

【讨论】:

这就是为什么正确/准确地命名“事物”很重要。我建议将clickHandler 重命名为onClick,因为这是几乎任何使用“按钮”组件的人所期望的,只是因为它是一个简单的“按钮”上下文。【参考方案2】:

似乎您的按钮应该使用上下文提供的功能,即usedLanguage.changeToPl 而不是LanguageContext.changeToPl

const usedLanguage = useContext(LanguageContext);

...

<Button text='pl' color=variables.DIMGRAY onClick=usedLanguage.changeToPl />
<Button text='en' color=variables.DIMGRAY onClick=usedLanguage.changeToEn />
<Button text='de' color=variables.DIMGRAY onClick=usedLanguage.changeToDe />

您还应该确保初始上下文值与组件实际使用的形状相匹配。

const LanguageContext = React.createContext(
  language: '',
  changeToPl: () => ,
  changeToEn: () => ,
  changeToDe: () => 
);

【讨论】:

同理,我尝试了console.log()文本,点击后还是没有答案。 @Paweł 你指的是状态更新后的控制台日志(console.log('pl');)吗?您能否提供一个运行的代码框来重现我们可以在其中进行调试的这个问题? 我在沙盒中重新创建了简化版本,它工作正常 - 不知何故它不能很好地转化为我的项目。 codesandbox.io/s/cranky-pine-68sd6?file=/src/Navbar.js

以上是关于使用 React Hooks 和 Context API 更改语言的主要内容,如果未能解决你的问题,请参考以下文章

如何将 React Context 与 Hooks 一起使用?

React Context 和 Hooks API 的酶错误

使用 React Hooks 和 Context 检查电子邮件是不是已经存在于 Firestore 的集合中

React 系列 02❤️ Custom Hooks 中使用 React Context

如何使用 React Hooks 和 Context API 正确地将来自 useEffect 内部调用的多个端点的数据添加到状态对象?

React Context with Hooks 总是“落后一步”