9

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?

Thomas
  • 1,512
  • 3
  • 12
  • 37

1 Answers1

3

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> 
diedu
  • 19,277
  • 4
  • 32
  • 49
Caerbannog
  • 790
  • 3
  • 8
  • Even though it is not using hooks I think this is preferable as it avoids utilizing undocumented (and potentially unsupported) code. – Thomas May 25 '21 at 12:19