如何为Flow中嵌套在HOC中的组件键入props?

时间:2018-02-14 15:25:40

标签: reactjs visual-studio-code flowtype

我发现在HOC中包装组件不会返回任何类型的注释。

简短的例子:

组件/按钮/ index.js

// @flow

import * as React from 'react'
import { withRouter } from 'react-router-dom'
import styled from 'styled-components'

const Wrapper = styled.button`
  background-color: transparent;
`

type Props = {
  children?: React.Node,
  history: Object,
  target: String
}

const Button = (props: Props) => {
  return <Wrapper onClick={() => { if (props.target) props.history.push(props.target) }}>{props.children}</Wrapper>
}

export default withRouter(Button)

但是在另一个组件中使用它时,VS Code不会提供有关我的Button组件的任何信息:

enter image description here

它应该是这样的:

enter image description here

那么我该如何编写那些类型注释?

更新1

这是我目前的解决方案,基于评论和一些研究(类型的交集):

// @flow

import * as React from 'react'
import { RouterHistory, withRouter } from 'react-router-dom'
import styled from 'styled-components'

import theme from 'themes/default'

type ButtonProps = {
  children: React.Node,
  target: string,
}

type Props = ButtonProps & RouterHistory

const Wrapper = styled.button`
  background-color: transparent;
`

const Button = ({ children, history, target }: Props) => (
  <Wrapper onClick={() => { history.push(target)}}>{children}</Wrapper>
)

const enhanced: typeof Button = withRouter(Button)
export default enhanced

我确信有更好的解决方案,但如果没有输入类型,VS代码将不会显示除import Button之外的任何提示。

1 个答案:

答案 0 :(得分:2)

我猜Props的类型是错误的。使用flow-typed的类型定义,ContextRouterwithRouter HOC提供的其他道具的类型。

import type { ContextRouter } from 'react-router';

type Props = ButtonProps & ContextRouter;

我在REPL上发了an example

替代方法

HOC很难输入,因为流量需要从history的道具中减去 Button等。另一种选择是"render props" pattern。流程进行类型检查要容易得多,因为它不需要减法。

幸运的是,withRouter只是Route组件的一个薄包装,需要render道具。

如果您使用Route,则可以直接使用ButtonProps,以便流程更容易理解。

type ButtonProps = {
  children: React.Node,
  target: string,
}

const Button = ({ children, target }: ButtonProps) => (
  <Route
    render={({ history }) => (
      <button onClick={() => { history.push(target) }}>{children}</button>
    )}
  />
)

export default Button

我还用REPL做了a working example with render prop