如何在React中使用Flow类型?

时间:2016-12-26 20:31:45

标签: javascript reactjs types ecmascript-6 flowtype

假设我有一个App组件,其状态由一个对象组成,其形状由以下Flow类型给出:

type Person = {
    fname: string,
    lname: string
};

要声明我的组件的状态确实是Person类型,我在getInitialState中创建一个人工局部变量,以便我可以注释该类型:

const App = React.createClass({
    getInitialState: function() {
        const person : Person = {fname: 'John', lname: 'Doe'};
        return {person: person};
    }
    , render: function() {
        return (
                <PersonDetails person={this.state.person}/>
        );
    }
});

以上作品(即使必须声明const person是一个小小的不便)。 当我希望将该状态作为另一个组件的属性传递时,就会出现问题。在这种情况下,我找不到其他解决方案,只能使用React的PropTypes API重新定义Person的形状:

const PersonDetails = React.createClass({
    propTypes: {
        person: React.PropTypes.shape({fname: React.PropTypes.string.isRequired,
                                       lname: React.PropTypes.string.isRequired}).isRequired
    },
    render: function() {
        return (
                <div>
                <span>{this.props.person.fname}</span>
                <span>{this.props.person.lname}</span>                
                </div>
        );
    }
});

这显然不是DRY加上我使用两种不同的方法来提供静态类型信息(Flow和React.PropTypes API)。

有没有办法允许PersonDetails组件重用Person的类型声明?

我找到的唯一方法是使用适当的类(而不是React类型):

class Person {
    fname: string;
    lname: string;
    constructor(fname: string, lname: string) {
        this.fname = fname;
        this.lname = lname;
    }
};

const PersonDetails = React.createClass({
    propTypes: {
        person: React.PropTypes.instanceOf(Person).isRequired

    },
    render: function() {
        return (
                <div>
                <span>{this.props.person.fname}</span>
                <span>{this.props.person.lname}</span>                
                </div>
        );
    }
});

const App = React.createClass({
    getInitialState: function() {
        const person : Person = new Person('John', 'Doe');
        return {person: person};
    }
    , render: function() {
        return (
                <PersonDetails person={this.state.person}/>
        );
    }
});

export default App;

...虽然以上成功重用了这个定义,但是当我应该使用Flow类型与类来静态类型检查我的组件时,我不清楚。另外,我不确定这两种方法是否真正等效(例如,在能够表示值的无效能力方面)。

1 个答案:

答案 0 :(得分:2)

声明您的类型一次并导出它:

// types/index.js

export type Person = {|
  fname: string,
  lname: string,
|}

然后在任何地方重复使用它。

在组件的state中:

// App.js

import type { Person } from './types'

type State = {|
  person: Person,
|}

class App extends Component {
  state: State = {
    person: { fname: 'John', lname: 'Doe' },
  }

  render() {
    return (
      <PersonDetails person={this.state.person} />
    )
  }
}

在组件的props中:

// components/PersonDetails.js

import type { Person } from '../types'

type Props = {|
  person: Person,
|}

// stateful syntax
class PersonDetails extends Component {
  props: Props

  render() {
    const { person } = this.props
    return (
      <div>
        <span>{person.fname}</span>
        <span>{person.lname}</span>               
      </div>
    )
  }
}

// stateless syntax
const PersonDetails = ({ person }: Props) => (
  <div>
    <span>{person.fname}</span>
    <span>{person.lname}</span>               
  </div>
)