title: React app keeps refreshing when changing i18next language in combination with authenticated routes
body: <p>I have a react-app with authentication (cookie based) with a login route and a profile route. The profile route is fetching the profile data and puts the data in a form. One of the fields is a language field. I'm using the <code>useEffect</code> hook to watch the language property and use <code>i18n.changeLanguage()</code> to change the language.</p>
  <p>For some reason the page keeps refreshing when I add this code. It must be a combination of this code together with the code I'm using the check if the user is authenticated to access the route. When I comment out the protectedRoute function or the useEffect hook it's working but I obviously need both.</p>
  <p>A small breakdown of the protectedRoute function and authContext.</p>
  <p>The routes are wrapped in an AuthProvider</p>
  <pre><code>const App = () =&gt; {
      return (
          &lt;BrowserRouter&gt;
              &lt;AuthProvider&gt;
                  &lt;Router /&gt;
              &lt;/AuthProvider&gt;
          &lt;/BrowserRouter&gt;
      );
  };
  </code></pre>
  <p>Inside the AuthProvider I have a <code>user</code> and <code>isAuthenticated</code> state. Both starting with a value of <code>null</code>. On mount a call with or without a cookie is done to the backend to get the user info. If a user object is returned with an id the <code>isAuthenticated</code> state is set to true.</p>
  <pre><code>const AuthProvider = ({ children }) =&gt; {
    const [isAuthenticated, setIsAuthenticated] = useState(null);
    const [user, setUser] = useState(null);
  
    useEffect(() =&gt; {
      getUserInfo();
    }, []);
  
    const getUserInfo = async () =&gt; {
      try {
        const { data } = await authService.me();
  
        setIsAuthenticated(true);
        setUser(data);
      } catch (error) {
        setIsAuthenticated(false);
        setUser({});
      }
    };
  
    const setAuthInfo = (user) =&gt; {
      setIsAuthenticated(!!(user &amp;&amp; user.id));
      setUser(user);
    };
  
  ...
  </code></pre>
  <p>As long as isAuthenticated is <code>null</code> a loading state is rendered instead of a route.</p>
  <pre><code>  if (authContext.isAuthenticated === null) {
      return (
        &lt;div&gt;
          &lt;span&gt;Loading...&lt;/span&gt;
        &lt;/div&gt;
      );
    }
  
    const ProtectedRoutes = () =&gt; {
      return authContext.isAuthenticated ? (
        &lt;Outlet /&gt;
      ) : (
        &lt;Navigate to=&quot;/login&quot; replace /&gt;
      );
    };
  
    return (
      &lt;Routes&gt;
        &lt;Route path=&quot;/login&quot; element={&lt;Login /&gt;} /&gt;
  
        &lt;Route element={&lt;ProtectedRoutes /&gt;}&gt;
          &lt;Route path=&quot;/&quot; element={&lt;Navigate to=&quot;/profile&quot; replace /&gt;} /&gt;
          &lt;Route path=&quot;/profile&quot; element={&lt;ProfileOverview /&gt;} /&gt;
        &lt;/Route&gt;
      &lt;/Routes&gt;
    );
  </code></pre>
  <p>The profile page can be accessed when the <code>isAuthenticated</code> state is true. Inside the profile page the user profile information is fetched and with a reset set into the form state. This will trigger the useEffect hook watching the <code>formData.language</code> property which will set the language to the user's language. This leads to a continuous refresh and I can't find the reason why or what I'm doing wrong.</p>
  <pre><code>const Profile = () =&gt; {
    const { i18n } = useTranslation();
  
    const { formData, reset, handleSubmit, handleChange } = useForm({});
  
    useEffect(() =&gt; {
      console.log(&quot;Get profile data&quot;);
      getProfileInfo();
    }, []);
  
    useEffect(() =&gt; {
      i18n.changeLanguage(formData.language);
    }, [formData.language]);
  
    const getProfileInfo = async () =&gt; {
      const { data } = await profileService.getProfileInfo();
      reset(data);
    };
  
    const submit = (values) =&gt; {
      console.log(&quot;submit&quot;);
    };
  
  ...
  </code></pre>
  <p><a href="https://codesandbox.io/s/reverent-feather-ncd0q9?file=/src/pages/Profile.js" rel="nofollow noreferrer">Codesandbox demo over here</a>. I have put a console.log inside the useEffect on the profile page so you can see that it keeps refreshing. Login can be done without credentials. All fetches are done with a setTimeout to fake real calls.</p>