react-i18next: `useTranslation` returns an unstable reference to `t`
I tried searching for mentions of unstable reference to t
returned by useTranslation
and did not find anything. Also, the docs do not mention whether the reference is expected to be stable or not.
–>
🐛 Bug Report
useTranslation
returns an unstable reference of t
, this causes problems when using it on other hooks.
To Reproduce
const { t } = useTranslation('fakespace');
// when not ready, `t` is always a different function every time `useTranslation` is invoked.
Expected behavior
t
should return a stable reference if arguments to useTranslation
have not changed.
Your Environment
- runtime version: i.e. node v14, webpack, chrome
- i18next version: i.e. 19.8.4
- os: Mac
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 10
- Comments: 25 (12 by maintainers)
@tigerabrodi The problem is for example if I’m using
t
in auseEffect
to show a user a localized notification, I need to make sure I have the latest and correct reference tot
in theuseEffect
hook, so I want to includet
in its dependencies. Ift
is not stable, then it will cause myuseEffect
to needlessly rerun all the time. It doesn’t have to be a notification, it could be anything involving some string I need to localize in a hook that depends ont
.Roughly something like:
I’m curious if there is any plan/progress on this issue, the only workaround I came up with was totally remove
t
from dependency array of hooks likeuseEffect
(it triggers API calls in my case) , don’t know if that has any negative consequences.I did not find how to solve the problem but here we can see the problem with the less code possible: https://codesandbox.io/s/snowy-hill-vwljzl?file=/src/index.js
Open the terminal of the codesanbox and you’ll see:
As @kitsunekyo , I use t() to display a toast in useEffect and for now the only solution that I found is to use i18n.t()
NB: The first two renders are due to React 18: https://reactjs.org/docs/strict-mode.html#ensuring-reusable-state
Yeah, this one is a bit tricky, one thing is for sure though, we wanna memoize it haha 😄
@thiagoevg
do you really have an issue? or is there just something in your code that is sub-optimal?
looking at the problem and possible solution:
a) make
t
“stable” not changing if language changes or translations are loaded -> result your popup is filled with either no translations or wrong language depending on what triggered the change oft
b) not using
t
in the dependency array (which should not be named dependency array but props array -> as only those are needed to set there which trigger a rerender on change) -> same result as a) your text in the popup is wrongc) don’t set the popup text but
setPopupKey("Error_Key")
-> and do based on that error key the translations inside the rendering of your popupas a general rule -> keep translation as close as possible to the rendering and as far as possible from API calls
Just noticed this same problem on our project, a useEffect hook was constantly firing.
Switching from
to
solved the issue for us.
Nah sorry about that, I didn’t mean to get help with my code hahaha. What I meant was, I thought
t
is a function which takes an argument and depending on some global state (i18n object and its resources itc) returns a string, but seems it is more complicated than that.I think the example was too small to make it obvs 😬 Thanks for the clarification @jamuhl
@eomuraliev if you end in
if (!i18n)
it actually tells you - your config/setup is broken!!! you should never get into that execution path - it only exists to warn you that you got something wrong.t
function gets only set if something changes, same for the ready boolean (which as a boolean is a type and not a ref)Isn’t mandatory to pass
i18n
instance toreact-i18next
?k
is an argument, so you could get away with just wrappingnotReady
in auseCallback
with an empty dependencies array. Also, you would need to lift the declaration ofnotReady
up out of theif
, since hooks should not be conditionally invoked.I removed my guesses for where the problem is caused or how to solve it. I could be wrong on the causes, and I don’t want it to distract from the discussion that
t
should be stable.