79665569

Date: 2025-06-14 04:23:51
Score: 2
Natty:
Report link

Why is throw redirect('/login') not redirecting but rendering errorElement instead?

I was working with React Router's data APIs and using throw redirect("/login") in my loader functions to protect routes. However, instead of redirecting to /login, React Router was rendering the errorElement for that route or showing an error response.

I found that manually setting response.body = true after calling redirect() made it work (got this idea from this post answer of this guy https://stackoverflow.com/a/76852081/13784221 :

import { redirect } from "react-router-dom";  
export async function requireAuth() {   
    const isLoggedIn = false;   
    if (!isLoggedIn) {     
        const response = redirect("/login");     
        response.body = true; // 👈 This made it work!     
        throw response;   
    }
    return null;
} 

Explanation: Why this works (based on React Router internals)

This issue is related to how React Router internally handles thrown Response objects in loaders and actions. It distinguishes between:

When I throw redirect("/login"), it creates a Response object with status = 302 and no body. Now, when you also provide an errorElement, React Router plays safe and tries to render it unless it's very sure you're doing a proper redirect.

React Router checks for:

error instanceof Response && error.status >= 300 && error.status < 400 && error.bodyUsed 

So if bodyUsed is false, it falls back to showing the errorElement.

The Hacky Fix: Setting response.body = true

Setting response.body = true (or even response.bodyUsed = true) tricks React Router into treating your Response object as “used” and safe to redirect.

So this:

const response = redirect("/login"); 
response.body = true; 
throw response;

...acts as if the redirect body has been processed, and skips rendering the errorElement.


Reasons:
  • Blacklisted phrase (1): stackoverflow
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • Self-answer (0.5):
  • Starts with a question (0.5): Why isnot
  • Low reputation (1):
Posted by: dipanshuuu