Home > Software design >  React route pass-through
React route pass-through

Time:01-17

I have a React-Typescript UI running on top of a flask API. I'm using BrowserRouter for routing paths in the UI. For a couple routes I want the react app to just fall back to rendering raw HTML returned by the underlying flask app. ie I don't want to map the route to an element, just fetch the route from the back-end. Is there some way to tell the route to behave this way?

Edit: Here's a detailed outline of the issue:

The react app is a thin client over top of a flask app. When requests come in the front door, the flask app either handles the request, or re-routes it to the react UI:

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
    if path.startswith("api/v0/"):
        abort(404)
    if current_user.is_authenticated and current_user.is_active:
        return render_template("ui/index.html")
    elif current_user.is_authenticated:
        return render_template("inactive.html")
    else:
        return render_template("unauth.html")

The flask app has a /logout route, that unloads the current user and then redirects to the (flask-handled) / route, prompting unauth.html to load. This works fine when I directly navigate to /logout.

The React UI has its own router for loading page elements. Loading /ui/index.html launches the app, and it essentially defines its own namespace for rendering pages:

<Routes>
    <Route path="" element={<Navigate replace to="/collections" />} />
    <Route path="/" element={<App />}>
      <Route path="home" element={<Home />} />
      <Route path="collections">
        <Route path=":collectionId" element={<CollectionDetail />} />
        <Route index element={<CollectionsList />} />
      </Route>
      <Route path="users">
        <Route index element={<UserList />} />
      </Route>
      <Route path="images/:imageId" element={<ImageDetail />} />
    </Route>
    <Route
      path="*"
      element={
        <main>
          <p>Page not found</p>
        </main>
      }
    />
  </Routes>

The issue is I have no way to break out of the react app context once I'm in it. Specifically, placing a <Link /> to "/logout" takes the default route in the app and renders "Page not found". But if I navigate directly to /logout the flask app handles it correctly.

One solution might be to move all the html-generating flask responses to the react app, but I think this would complicate routing in the flask app itself- ideally flask is only aware of the single entry point to the react app at /ui/index.html

CodePudding user response:

The Link component has a reloadDocument prop that can be used to "skip client side routing and let the browser handle the transition normally (as if it were an <a href>)". In doing so this a page request is made to the server and can be handled there.

See Link.

interface LinkProps
  extends Omit<
    React.AnchorHTMLAttributes<HTMLAnchorElement>,
    "href"
  > {
  replace?: boolean;
  state?: any;
  to: To;
  reloadDocument?: boolean;
}

Example:

<Link to="/logout" reloadDocument>Logout</Link>
  • Related