如何刷新所有屏幕

How to refresh all screens

我正在使用 i18n.js 和 expo-localization 开发多语言应用程序。默认语言是系统默认语言,用户可以 select 他们的首选语言。但是在语言被 selected 之后,只有 StackActions.replace('MyDrawer') 下的那些屏幕被刷新并且语言改变了。其他屏幕仍使用默认语言。请问React Navigation有没有刷新所有界面的方法?

import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import i18n from 'i18n-js';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { StackActions } from '@react-navigation/native';


const LanguagePicker = ({navigation, route}) => {

  const [languageSelected, setLanguageSelected] = useState(null)
   
  const handleSelectLanguage = (n) => {
    setLanguageSelected(n)
    AsyncStorage.setItem('storedLanguage', n)
    navigation.dispatch(
      StackActions.replace('MyDrawer'))
  }

  i18n.locale = languageSelected
  console.log("i18n.locale in language picker", i18n.locale)

return(

  <View style={styles.container}>
 
  <TouchableOpacity onPress={() => {handleSelectLanguage('pt')}}>
      <Text style={styles.text}>Português</Text>
  </TouchableOpacity>
  <TouchableOpacity onPress={() => {handleSelectLanguage('en')}}>
      <Text style={styles.text}>English</Text>
  </TouchableOpacity>
</View>
)}

我最终使用 Context 来管理语言的全局状态。

在Context.js

import React, {useState, useEffect} from 'react'
import AsyncStorage from '@react-native-async-storage/async-storage';
import i18n from '../config/i18n';


const Context = React.createContext()

export const Provider =({children}) => {
    const [language, setLanguage] = useState(i18n.locale)

     // In the beginning of App, check if user has selected language before. 
     // If not, use system default language
     useEffect(()=> {
        AsyncStorage.getItem('storedLanguage').then(data => {
             if (data === null) {
             setLanguage(Localization.locale)
             }
             else {setLanguage(data)}  
              
             console.log('language inside useEffect', language)          
             }).catch((error) => console.log(error))    
       }, [])
 
    
    const userChangeLanguage = async (language) => {
        setLanguage(language)
        await AsyncStorage.setItem('storedLanguage', language)  
    }
    
    return (
    <Context.Provider value={{data: language, userChangeLanguage}}>
         {children}
    </Context.Provider>)   
}
export default Context

然后像这样将 App.js 包裹在提供程序中:

import React from 'react'
import Navigation from './scr/navigation/Navigation'
import { Provider } from './scr/context/Context'

const App = () => {
  return (
    <Navigation/>
  )
}

export default () => {
  return <Provider>
  <App/>
  </Provider> 
}

在 LanguagePicker.js 屏幕中:

import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import Context from '../context/Context';
import React, { useContext } from 'react';
import { StackActions } from '@react-navigation/native';

const LanguagePicker = ({navigation}) => {

  const {userChangeLanguage} = useContext(Context)

  const handleChangeLanguage = (language) => {
    userChangeLanguage(language);
    navigation.dispatch(StackActions.replace('MyDrawer'))
  } 
  
return(

  <View style={styles.container}>
 
  <TouchableOpacity style={styles.button} onPress={()=>handleChangeLanguage('zh')}>
      <Text style={styles.text}>繁體中文</Text>
  </TouchableOpacity>
  <TouchableOpacity style={styles.button}  onPress={() => handleChangeLanguage('zh-Hans')}>
      <Text style={styles.text}>简体中文</Text>
 </TouchableOpacity>

etc...

最后,在Navigation.js中,从Context中获取数据(语言)并设置i18n.locale = data

const Navigation = () => {
      
      const {data} = useContext(Context)

      i18n.locale= data;

或者,可以使用博览会更新。强制整个应用程序检查最新更新只是为了刷新语言绝对是一种矫枉过正。一旦按下一种语言,应用程序将重新启动。不是最流畅的用户体验,但也不算太糟糕。考虑到它只需要一行代码,所以我仍然认为它是一种快速而肮脏的解决方案。

const [languageSelected, setLanguageSelected] = useState(i18n.locale)
   
const handleSelectLanguage = (n) => {
    setLanguageSelected(n)
    AsyncStorage.setItem('storedLanguage', n)
    Updates.reloadAsync()
}

i18n.locale = languageSelected