为了减少编码过程中可能出现的问题,我们制定了如下规范,希望能减少常见的错误。
有状态组件只有 render
方法才能返回 JSX,因为 JSX 中的虚拟 DOM 有一个 _owner
属性,这与它与组件实例进行绑定。如果其他方法里使用了 JSX, _owner
就没有与组件实例进行绑定。
render
方法里面应该以 <
开头,不应该存在 if else
分支,视情况返回不同的JSX。相同的组件应该返回相同的顶级元素容器。
// 不好的实践
render() {
if (this.state.a) {
return <strong>不要</strong>
} else {
return <div>这样</div>
}
}
// 不好的实践
<Foo
ref="myRef"
/>
// 一般的实践
<Foo
ref={(ref) => { this.myRef = ref; }}
/>
上面的方法之所以是一般的实践,而不是好的实践,是因为我们在查看组件时,别人很难察觉到你在 JSX 里偷偷为组件添加了一个新属性。组件所有用到的属性,应该都能在 constructor
或 defaultProps
中找到。
refs.xxx
中的 DOM 节点,不应该再转存到组件实例上或其他地方中。每次访问 refs.xxx
必须判定其是否为空。
不要在 componentWillUpdate/componentDidUpdate/render
中执行 setState
, 可能导致死循环。
不要在 JSX 中使用 bind
方法绑定组件实例
// 不好的实践
class extends React.Component {
onClickDiv() {
// do something
}
render() {
return <div onClick={this.onClickDiv.bind(this)} />;
}
}
// 好的实践
class extends React.Component {
constructor(props) {
super(props);
this.onClickDiv = this.onClickDiv.bind(this);
}
onClickDiv() {
// do something
}
render() {
return <div onClick={this.onClickDiv} />;
}
}
不要使用 cloneElement
, createElement
, 让 JSX 与 babel 帮你创建它们。
不要使用 createClass
, mixin
, PropTypes
(它们已经被移出核心库,被逐渐边缘化,有关属性的描述改成文档注释吧)。