【问题标题】:Changing language with React Hooks and Contex API使用 React Hooks 和 Context 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,但现在我想处理所描述的问题。

【问题讨论】:

    标签: reactjs react-hooks state context-api


    【解决方案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
    猜你喜欢
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 2020-02-23
    • 1970-01-01
    • 2020-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多