Do you want to request a feature or report a bug?
Question. This may also be related to #14563.
How do we trigger suspense from a hook?
Why did the question come up?
This question came up during our usage of react-i18next
. A recent update of react-i18next
provided the useTranslation
-hook which allows obtaining the current translations and will also trigger loading of not-yet-loaded translation namespaces (kinda like code splitting).
To handle the case where the translations aren't loaded yet, the useTranslation
-hook throws a promise to trigger Suspense
, which is actually really neat because it cleanly integrates with the existing react features!
However, if you are using more hooks after calling the useTranslation
-hook, these other hooks won't be rendered if useTranslation
throws the promise. Once the translations have loaded the hook won't throw anymore and react will award you with a big red warning that the amount of hooks has changed.
Example
const Component = () => {
const [t] = useTranslation('translationnamespace');
const [count, setCount] = useState(0);
return (
<div onClick={() => setCount(count + 1)}>
{t('The count is:')} {count}
</div>
);
};
If translationnamespace
isn't loaded yet, useTranslation
will throw, causing useState
to not be rendered. Once translationnamespace
is loaded, useTranslation
won't throw anymore, which causes useState
to be rendered causing the warning.
The General Case
So this question doesn't apply to react-i18next only, but instead applies to all hooks that wish to trigger suspense. How would we go about doing this, and how would this integrate with the current "Rules of Hooks" that state that hooks mustn't be rendered conditionally?
It seems like a mistake that the error fires in case of suspending. Afaik that was not intentional.
Alright, good to know!
Might also want to document that it is defined behavior to not render all hooks in case of suspension. But I presume this will be done once suspension is officially introduced as a data-fetching mechanism.
I think we actually fixed this in 16.8.2. Please open a new one with a reproducing case if not.
Most helpful comment
I think we actually fixed this in 16.8.2. Please open a new one with a reproducing case if not.