简体   繁体   中英

Extending props with the withRouter HOC in Next.js

I'm trying to use withRouter HOC helper in the Next.js library.

import { withRouter } from 'next/router'

const MyComponent = withRouter(({ router }) => ())

This gives a flow error:

[flow] property `router` is missing in props [1]. (References: [1])

Even though I have the flow types installed for Next.js and withRouter function has the following signature:

withRouter: < T > (Component: React$ComponentType < (T & {
  router: Router
}) > ) => class React$Component

I thought flow would work out that router is injected by withRouter, but that doesn't seem to be the case? How do I fix this type error?

I tried importing the Router type and declaring it as a prop:

import { Router } from 'next/router'

type Props = { router: Router }
const MyComponent = withRouter(({ router: Router }: Props) => ())

This removes the error, but now I get a different one:

Property router is missing in props [1] but exists in object type [2].

 [1] 61│         {typeof query.post !== 'undefined' && <Post />}

 [2] 29│ const Basic = withRouter(({ router }: { router: Router }) => (

Try adjusting the types of withRouter to this:

withRouter: <T: {}>(
  React$ComponentType<{
    ...$Exact<T>,
    router: Router,
  }>,
) => React$ComponentType<T>

And on your component file, you'll have to cast the result of enhancing the base component with the outer props, which for now I'm just putting an empty object.

const MyComponent = ({ router }) => (/* some jsx */)


export default (withRouter(MyComponent): React$ComponentType<{}>)

OK, I think I got this.

withRouter is a function typed with generics and is parametrized with T.

There's a section in flow docs about generics: https://flow.org/en/docs/types/generics/ .

One way to call such a function is by passing in the T type when calling:

import { withRouter } from 'next/router'
import type { Router } from 'next/router'

type Props = {}

type PropsWithRouter = Props & {
  router: Router
}

const MyComponent = withRouter<Props>(({ router }: PropsWithRouter) => ())

This passes the flowtype check and the component can be used without passing in the Router at the call site.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM