react 开发规范(极简)

521 阅读2分钟

前言

本文旨在将日常开发过程中遇到的坑,或者维护起来很麻烦的写法做记录,精简为如下10条规则,其中可以通过 eslint 与 prettier 的规则解决的格式与风格的问题在此不再赘述。


rules

你我约定难过的往事不许提,也答应永远都不让对方担心~


1. 禁止在 DOM 元素中使用 dangerouslySetInnerHTML 属性。

// 💢bad
<div className={classname} dangerouslySetInnerHTML={{ __html: html }} />

// ✅good
const htmlValue = process(html); // escape or get useful msg
<div value={htmlValue} />


2. 不要在 JSX 属性中使用 .bind()。因为 render 时创建新的函数,会影响性能。
// 💢bad
class Demo extends PureComponent {
  onClick() {
    // ...
  }

  render() {
    return <div onClick={this.onClick.bind(this)} />;
  }
}

// ✅good
class Demo extends PureComponent {
  onClick = () => {
    // ...
  }

  render() {
    return <div onClick={this.onClick(this)} />;
  }
}


3. 不要传递实例的引用,因为 react 16 之后的版本 render 不一定是同步的,使用实例的方法时机不一定正确。


4. 不是 isRequired 的 props 必须设置默认值,组件可以接受外部的 className
class Demo extends PureComponent {
    static propTypes = {
      visible: PropTypes.bool,
      onChange: PropTypes.func,
      className: PropTypes.string,
    }

    // 不是isRequired的props必须设置默认值
    static defaultProps = {
      // 每个组件都应该能接受外界传入的className值
      className: '',
      visible: false, 
      // 回调函数的默认值可以用lodash提供的空函数
      onChange: noop,
    }
}


5. 组件不要修改 props, 函数不要突变
import update from 'immutability-helper';

class Demo extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      data: this.initData(props),
    };
  }
  
  // 💢bad
  initData = (props) => {
    props.data = []
    
    return props;
  }
  
  // ✅good
  initData = (props) => {
    return update(props, {
      data: { $set: [] }
    });
  }
}


6. 不要使用模糊的类型验证,推荐 ts, 但 ts 的规则同理
class Demo extends React.Component {
  ...
}

// 💢bad
Demo.propTypes = {
  list: PropTypes.array,
  info: PropTypes.onject,
  status: PrpoTypes.any
};

// ✅good
Demo.propTypes = {
  list: PropTypes.arrayOf(PropTypes.string),
  info: PropTypes.shape({
    title: ProTypes.string,
    count: ProTypes.number
  }),
  status: PrpoTypes.bool
};


7. 组件需要有 componentDidCatch, catch 中需要上报信息。
class Demo extends React.Component {
  constructor(props) {     
    super(props);     
    this.state = { error: false };
  }
  
  componentDidCatch(error, info) {     
    this.setState({ error, info });
  }
  
  render() {
    if (this.state.error) {
      return <ErrorUI />;
    }
    
    return <NormalUI />;   
  } 
}


8. 不要使用 index 做任何事情,包括不限于 1. 组件的key,2. 实体的 id, 3. 唯一性的标志位 😑


9. 样式文件要有自己的作用域
// 💢bad
.title {
  ...
}

// ✅good
.report-list {
  ...
  
  .title {
    ...
  }
}


10. 删除组件引用时,小心样式的副作用问题
// A component
import React, { PureComponent } from 'react';
import './index.less'; // 样式文件作为副作用引入

class A extends PureComponent {
  ...
}
  
// B component
import A from '..components/A'; // 这里就算不用 A 组件的逻辑,也会使用 A 组件的样式

class B extends PureComponet {...}