Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

t is unstable in appDir #1205

Open
jessemartin opened this issue Apr 1, 2024 · 1 comment
Open

t is unstable in appDir #1205

jessemartin opened this issue Apr 1, 2024 · 1 comment

Comments

@jessemartin
Copy link

What version of this package are you using?
2.6.2 (appDir)

What operating system, Node.js, and npm version?
N/A (present in all)

What happened?
The t function returned by the useTranslation hook is not stable.

Consider this problematic usage scenario, for example:

const { t } = useTranslation();

const [message, setMessage] = useState('');

const updateMessage = useCallback((evt) => { setMessage(evt.target.value); }, []);

const [triggerPostMessage, { isError: isPostMessageFailedError }] = usePostMessageMutation();

const postMessage = () => triggerPostMessage(message);

// This effect shows an error message if the post message request failed.
// `showToast` and `isPostMessageFailedError` are stable -- their references do not change when the component re-renders.
// However, `t` is unstable. So, every time this component re-renders (say, as `message` state is being updated by the user typing), this useEffect runs again, resulting in an additional toast being shown if in the error state.
// If `t` were instead stable, the effect would run only on `isPostMessageFailedError` transitions. And one toast would be shown when a transition into the error state occurs.
// There are many ways to work around this problem, but doing so should not be needed. `t` should be stable unless there is a good reason for it not to be.
useEffect(() => {
  if (isPostMessageFailedError) {
    showToast(t('post_message_failed_error_message'));
  }
}, [isPostMessageFailedError, showToast, t]);

return (
  <>
    <input onChange={updateMessage} value={message} />
    <button onClick={postMessage}>{t('post_message_button_text')}</button>
  </>
);

What did you expect to happen?
t should be a stable reference. This way, hooks that depend on it do not change on every render.

Are you willing to submit a pull request to fix this bug?
Yes, time allowing

@jessemartin
Copy link
Author

PR here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant