Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access staticContext through hook in react-router

I want to create a generic "not-found" component that sets the statusCode to 404 if the StaticRouter is used. I know that I can do this:

<Route
  render={(routeComponentProps) => <NotFound {...routeComponentProps} />}
/>

Or use a child function as the doc describes, but as my app is growing in complexity I'd like to simplify it down to the way I specify all my other routes in order to avoid having to remember to pass props to the NotFound component. Something like this:

<Route>
  <NotFound />
</Route> 

This means I'd like to access staticContext inside <NotFound/> using a hook (preferrably), but unfortunately that does not seem possible at this time as the useRouteMatch hook does not return staticContext.

My current workaround is to grab __RouterContext from inside react-router and pass it to a useContext hook, but this seems hacky and is probably not supported. However it does work fine both server-side and client side (using the normal BrowserRouter)

import React, { useContext } from "react"
import { __RouterContext } from "react-router"

export const NotFound: React.FC = () => {
    const { staticContext } = useContext(__RouterContext)
    if (staticContext) {
        staticContext.statusCode = 404
    }

    return (
        <div>
            <h3>404: Not found</h3>
        </div>
    )
}

export default NotFound

Is there a hook I can use or perhaps plans to start supporting this within the useRouteMatch hook?

like image 349
Thomas Avatar asked Jun 14 '20 08:06

Thomas


People also ask

How do I pass to prop link react router?

To recap, if you need to pass data from Link through to the new component that's being rendered, pass Link s a state prop with the data you want to pass through. Then, to access the Link s state property from the component that's being rendered, use the useLocation Hook to get access to location.

Can you pass props through react router?

With the react-router v5, we can create routes by wrapping with a component, so that we can easily pass props to the desired component like this. Similarly, you can use the children prop in v5. If you are using react-router v4, you can pass it using the render prop.

How do you navigate to an external URL in react router?

You can use the Link component or an HTML anchor tag if you want to redirect to an external link with React Router. Using the < Link > component, you can do it thanks to the pathname and target parameters. It will redirect the user to the specified URL.

How do you handle nested routes in react?

Nested Routes in React Router We will continue working on the User component, because this is the place where we want to have the nested routing via tabs. Therefore, we will instantiate a new set of Link components (which will be our unstyled tabs) which navigate a user to their profile and their account.


1 Answers

I don't think that you can access staticContext inside using a documented hook. If an undocumented hook existed it would not be a better workaround than your current __RouterContext trick (which I find quite elegant already).

You could do something though, if you relax your "hook" requirement. Which is probably OK: hooks are great to reuse logic, but don't need to be usedto solve every problem.

You can access the staticContext inside your <NotFound /> without any prop: you just need to add a newcatch-all <Route /> inside.

export const NotFound: React.FC = () => {
  return (
    <Route
      render={({ staticContext }) => {
        if (staticContext) {
          staticContext.statusCode = 404
        }

        return (
          <div>
            <h3>404: Not found</h3>
          </div>
        )
      }}
    >
  )
}

...

<Route>
  <NotFound />
</Route> 
like image 104
Caerbannog Avatar answered Oct 21 '22 14:10

Caerbannog