skip to Main Content

I write an SPA using the React library. I want to load some data from the backend using the REST API, and if the REST request returns an http 403 status to redirect the user to the sign-in page. The problem comes with the Strict Mode which mounts all the React components twice while in development mode.

This is the two methods that I tried to use:

// get the data from the backend (no data means http 403)
const response = useSuspenseQuery(...);

// first method: conditional return
if (response.data == null) {
  return <Navigate to='/sign-in' />;
}
// get the data from the backend (no data means http 403)
const response = useSuspenseQuery(...);

// second method: react hook
useEffect(() => {
  if (response.data == null) {
    navigate('/sign-in');
  }
}, [response]);

Both methods ended up redirecting to the sign-in page twice. As far as I understood, if something breaks while in the strict mode, that means that you are doing something wrong, the component mounting should be idempotent and not break stuff if done multiple times.

So that question is: how to correctly redirect user to the sign-in page, so that it wouldn’t break in strict mode?

2

Answers


  1. You can use this technique, where you retain a state to clearly govern the redirection, rather than verifying response.data directly in your component. try it like this

    const MyComponent = () => {
        const response = useSuspenseQuery(...);
        const [redirect, setRedirect] = useState(false);
    
        // Use useEffect to set the redirect based on the data
        useEffect(() => {
            // Check if the response data is null, indicating a 403 or other error scenario
            if (response.data === null) {
                setRedirect(true);
            }
        }, [response]);
    
        // If redirection is enabled, navigate to the sign-in page
        if (redirect) {
            return <Navigate to="/sign-in" />;
        }
    
        // Render your component's main content
        return (
            <div>
                {/* Your main content here */}
            </div>
        );
    };
    
    export default MyComponent;
    
    Login or Signup to reply.
  2. Between the two options you present it’s subjective which you choose, they both accomplish the same goal.

    With regards to React’s StrictMode component and the double-mounting/double-rendering of components if the issue you are seeing is that both <Navigate to="/sign-in" /> and navigate('/sign-in'); PUSH two entries onto the history stack then I’d suggest you instead use a REPLACE action, e.g. a redirect, so even if navigation is effected a second, or third, or even a forth time, the result is that only the current history entry is affected and any back navigation action from there correctly navigates back to the path the user was on prior to navigating to the path that ran the code you ask about here.

    Add the replace option to redirect instead of push.

    const response = useSuspenseQuery(...);
    
    useEffect(() => {
      if (response.data === null) {
        navigate('/sign-in', { replace: true });
      }
    }, [response]);
    
    const response = useSuspenseQuery(...);
    
    if (response.data === null) {
      return <Navigate to='/sign-in' replace />;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search