propTypeHandler: Improve support for detecting composition from code

未关闭
#9 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
5/5
预计耗时
一周以上
新手友好度
25/100
Issue 类型
功能
描述清晰度
基本清楚
活跃度
停滞
技术栈
javascript, react

调研方向

从 src/handlers/propTypeHandler.js 开始,尤其关注 issue 中关联的 spread 表达式处理,并追踪当前 composition 的表示方式。完成标准是支持所请求的通用 spread 处理,以及与 issue 中所述示例一致的子集 include/exclude 元数据。

由索引模型根据 Issue 内容生成。

描述

improvement

Imagine you have a component A that composes component B and therefore also accepts the same props as B. For example:

var A = React.createClass({
  propTypes: ...,
  render: {
      return <B {...this.props} />
  }
});

react-docgen is actually able to identify this composition if you merge B's propTypes into A:

propTypes: {
  ...B.propTypes,
  // more of A's propTypes here
}

But this is not only useful to make react-docgen happy, it's actually a better description of A's API. react-docgen will try to resolve B to its module path and add that to the composes field, e.g.

{
  description: '...',
  props: {...},
  composes: ['path/to/B']
}

Note that while parsing A, react-docgen will not parse B. It is up to you to pass B to react-docgen, or process that file in any way necessary. That means react-docgen doesn't actually care what B is, which brings me to my first point.


Relax the constraints for the spread operator in propTypes

Right now, react-docgen will only consider composition if the expression used is of form X.propTypes, i.e. it has to be a member expression which access propTypes. While this is fine for most cases, it obviously closes the door for modules which don't expose a propTypes property.

For example, consider you have a module that just defines prop types which are used by multiple components:

// SharedPropTypes.js
module.exports = {
  foo: React.PropTypes.number
};

// A.js
var SharedPropTypes = require('./SharedPropTypes');
var A = React.createClass({
  propTypes: {
    ...SharedPropTypes
  }
});

// B.js
// similar to A.js

Of course you can argue that no composition is taking place here, but we still want to be able to get a complete description of A's and B's API. And given the fact that react-docgen actually doesn't care what the SharedPropTypes module is, there is not really a reason to restrict it to that cases.


Support for API subsets

If you are composing components then the "parent" component might not actually support all the props of the composed component. It may only support a subset and set some props itself. For example:

var A = React.createClass({
  propTypes: ...,
  render: {
    return <B foo={this.props.foo}, bar={42} />
  }
});

So, instead of merging the complete propTypes object B all you need is B.propTypes.foo (you could easily do foo: B.propTypes.foo in this particular case, but please bear with me and imagine you have more than one prop (react-docgen would also not be possible to understand that it refers to module B, but I don't have a good solution for that yet)).

Destructuring actually gives us a nice statically analyzable way to specify this:

var {props, to, include} = B.propTypes;
var A = React.createClass({
  propTypes: {
    props,
    to,
    include,
    // A's props
  }
});

We could easily analyze that props, to, include comes from the module B originates from and create an entry in documentation object of the form:

{
  description: '...',
  props: {...},
  composes: [{module: 'path/to/B', include: ['props', 'to', 'include']}]
}

Again, it's up to you how to process this information, but at least you have it.

This would also work for excluding props:

var {do, not, include, ...propTypes} = B.propTypes;
var A = React.createClass({
  propTypes: {
    ...propTypes,
    // A's props
  }
});

We could easily analyze that props, to, include comes from the module B originates from and create an entry in documentation object of the form:

{
  description: '...',
  props: {...},
  composes: [{module: 'path/to/B', include: [], exclude: ['do', 'not', 'include']}]
}

Obviously this is only going to be useful if a flat structure is exported from the included module. I don't have a good idea for nested structures yet, but I'm also not sure if (default) support is necessary (or even possible (there is only so much you can statically analyze)). I'd rather encourage devs to keep things simple.

主要语言
TypeScript
星标
3.8k
派生
316
平均合并
3 小时 28 分钟
30 天内合并 PR
6

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

reactjs/react-docgen 的其他 Issue

查看 reactjs/react-docgen 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。