You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
After a bit of debugging (but without having deep understanding of the inner workings of @tolgee/core), I think there is a race condition happening that sometimes results in new t function not being created after translations change. Since it is a race condition, it is not easy to create a minimal reproducible example, but if you are not able to reproduce it, I will try to find time to do it. I'll try to share/explain my finding and if my assumptions are wrong or I have misunderstood how it should be working, then sorry for the confusion.
The problem seems to be in the useTranslateInternal hook, more specifically these LOCs.
Problem:
isLoaded is hook scope variable, beings re-evaluated every time the component using the useTranslate hook is re-rendering. This mean it does not always reflect to actual tolgee instance state.
I think it would be more correct to push this value from the event stream when it changes instead of relying on component re-render to have correct/up-to-date value.
This effect creates new subscription and unsubscribes from the (previous) subscription that will be replaced by the new. The culprit (and the question I haven't figured out - "why is it needed?") here is that it depends on isLoaded (which depends on component re-renders), meaning unsubscribing and creating a new subscription is not determined only by input arguments and tolgee state, but also on how often the component is re-rendering.
self.onCacheChange.listen(({ value }) =>
self.onUpdate.emit([value.namespace], true)
);
Translation changes are emitted asynchronously (with delayed: true).
Now, If we put all this together:
It is possible that the component re-renders exactly when tolgee cache has updated, but the subscribers are yet not notified about the update.
If during this render isLoaded changes from false to true, it will unsubscribe, but not re-subscribe, since the useEffect hook is subscribing conditionally. This would not be a problem if event emitter would consider the subscribers at the moment of the event happening, but since it is not, it does not call the subscribers that unsubscribe after the event happening, but before the callbacks/handlers are being called.
Since the race condition is triggered by component re-render, the issue is only revealed when the component is actually relying on the t function causing a re-render (calling t function inside React.useMemo that depends on t).
Unfortunately, I don't know the library well enough to suggest a change/PR at this point.
The text was updated successfully, but these errors were encountered:
Hey, thanks for detailed report. I think the mentioned part can be omited (if (!isLoaded) {).
It's already quite some time I've written this code and I think that was supposed to be some optimization, but I guess it did more harm than good.
Fixing #3247 and during that
I've found another bug, which occurs when in strict mode when not using
suspense, that loading state is resolved too early in TolgeeProvider
Reporting with the assumption (based on https://tolgee.io/js-sdk/integrations/react/api#function-t) that
t
function fromuseTranslate
hook should trigger component update/re-render when translations change.After a bit of debugging (but without having deep understanding of the inner workings of
@tolgee/core
), I think there is a race condition happening that sometimes results in newt
function not being created after translations change. Since it is a race condition, it is not easy to create a minimal reproducible example, but if you are not able to reproduce it, I will try to find time to do it. I'll try to share/explain my finding and if my assumptions are wrong or I have misunderstood how it should be working, then sorry for the confusion.The problem seems to be in the
useTranslateInternal
hook, more specifically these LOCs.Problem:
isLoaded
is hook scope variable, beings re-evaluated every time the component using theuseTranslate
hook is re-rendering. This mean it does not always reflect to actualtolgee
instance state.I think it would be more correct to push this value from the event stream when it changes instead of relying on component re-render to have correct/up-to-date value.
This effect creates new subscription and unsubscribes from the (previous) subscription that will be replaced by the new. The culprit (and the question I haven't figured out - "why is it needed?") here is that it depends on
isLoaded
(which depends on component re-renders), meaning unsubscribing and creating a new subscription is not determined only by input arguments andtolgee
state, but also on how often the component is re-rendering.https://github.com/tolgee/tolgee-js/blob/main/packages/core/src/Controller/Events/Events.ts#L58-L60
Translation changes are emitted asynchronously (with
delayed: true
).Now, If we put all this together:
tolgee
cache has updated, but the subscribers are yet not notified about the update.isLoaded
changes fromfalse
totrue
, it will unsubscribe, but not re-subscribe, since theuseEffect
hook is subscribing conditionally. This would not be a problem if event emitter would consider the subscribers at the moment of the event happening, but since it is not, it does not call the subscribers that unsubscribe after the event happening, but before the callbacks/handlers are being called.t
function causing a re-render (callingt
function insideReact.useMemo
that depends ont
).Unfortunately, I don't know the library well enough to suggest a change/PR at this point.
The text was updated successfully, but these errors were encountered: