微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 react-intl 和 mobx 状态树更新语言

如何解决使用 react-intl 和 mobx 状态树更新语言

这是我第一次将 react-intlMobx state tree 一起使用。

基本上我在标题中有两个按钮(iten),点击它们可以设置保存在 Mobx 状态树变量中的当前语言。

类似的东西。

在我的状态:

const FULL_LANGUAGE =
  (navigator.languages && navigator.languages[0]) || navigator.language || 'en-GB'
const LANGUAGE = FULL_LANGUAGE!.split('-')[0]

export const UIModel = t
  .model('UIModel',{
    language: LANGUAGE,})
  .actions((self) => ({
    setLanguage(language: 'it' | 'en') {
      self.language = language
    }
  }))

标题组件中:

...
<Button textToShow="it" onClick={() => setLanguage('it')} />
<Button textToShow="en" onClick={() => setLanguage('en')} />
...

我的 index.tsx 文件

import React from 'react'
import ReactDOM from 'react-dom'
import { IntlProvider } from 'react-intl'
import { stateInstance,Provider } from './state'
import { App } from './App'
import messagesIt from './locales/messages-it.json5'
import messagesEn from './locales/messages-en.json5'

const language = stateInstance.ui.language
const messages = language === 'en' ? messagesEn : messagesIt

function renderApp() {
  ReactDOM.render(
    <Provider value={stateInstance}>
      <IntlProvider locale={language} messages={messages}>
        <App />
      </IntlProvider>
    </Provider>,document.getElementById('root')
  )
}

renderApp()

和我的 Mobx 状态树根文件

import { createContext,useContext } from 'react'
import { Instance,types as t } from 'mobx-state-tree'
import { UIModel } from './UI'

export const StateModel = t
  .model('StateModel',{
    ui: t.optional(UIModel,{}),})

export const stateInstance = StateModel.create()
export interface StateInstance extends Instance<typeof StateModel> {}

const RootStateContext = createContext<StateInstance | null>(null)
export const Provider = RootStateContext.Provider

export function useMst() {
  const state = useContext(RootStateContext)
  if (state === null) throw new Error('')
  return state
}

问题是,当我点击 iten 按钮时,状态中的语言会更新,但我认为没有任何变化,因为 <IntlProvider locale={language} messages={messages}> 未“重新呈现”。>

我该如何解决

解决方法

有很多方法可以解决,例如我认为您可以将 IntlProvider 包裹在 Observer (docs) 组件中以使其具有响应性:

import { Observer } from 'mobx-react';

// ...

function renderApp() {
  ReactDOM.render(
    <Provider value={stateInstance}>
      <Observer>
        {() => (
          <IntlProvider
            locale={stateInstance.ui.language}
            messages={
              stateInstance.ui.language === 'en' ? messagesEn : messagesIt
            }
          >
            <App />
          </IntlProvider>
        )}
      </Observer>
    </Provider>,document.getElementById('root')
  );
}
,

这样解决:

const AppContainer: React.FC<{}> = observer(({}) => {
  const {
    ui: { language },} = useMst()
  return (
    <IntlProvider locale={language} messages={language === 'en' ? messagesEn : messagesIt}>
      <App />
    </IntlProvider>
  )
})

function renderApp() {
  ReactDOM.render(
    <Provider value={stateInstance}>
      <AppContainer />
    </Provider>,document.getElementById('root')
  )
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。