Search code examples
react-nativememory-leaksuse-effectuse-statei18next

i18next change language inside async causes memory leak


I allow the user to select a language within the app and I store it locally. When they come back in the app, I try using AsyncStorage to fetch the language but when I call

i18n.changeLanguage(currentLanguage)

it causes a memory leakage. here is my code

const [language, setLanguage] = useState('') 
    const {t} = useTranslation();    
    const fetchLanguage =  async () =>{
        try{
            const currentLanguage = await AsyncStorage.getItem('language')
            if (currentLanguage === null ){
            }
            else{
                setLanguage (currentLanguage)
                i18n.changeLanguage(currentLanguage)
            }
        }catch (e){
            console.log(e)
        }
       
    }
    useEffect (()=>{
        fetchLanguage()
    }, [])


Solution

  • Instead of trying to use i18n.changeLanguage(currentLanguage) inside the useEffect, use the language detector when you initialize i18next. you can then have a fault back language.The credit to this answer goes to Hend El-Sahli's answer here

    const initialLanguage = 'en'
    
    const languageDetector = {
      init: Function.prototype,
      type: 'languageDetector',
      async: true,
      detect: async callback =>{
        const storeLanguage = await AsyncStorage.getItem("language")
        const selectedLanguage = storeLanguage || initialLanguage
        callback(selectedLanguage)
      },
      cacheUserLanguage: () =>{}
    }
    
    
    i18n
      .use(initReactI18next) // passes i18n down to react-i18next
      .use(languageDetector)
      .init({
        resources: resources,
        compatibilityJSON: 'v3',
        fallbackLng:'en',
        interpolation: {
          escapeValue: false, // react already safes from xss
        },
    });
    
    export default i18n;