公司最近有个整理前端研发规范的政治任务,这里简单记录下目前社区已有的一些 React 代码风格的相关资源。
代码风格指南
- Airbnb React/JSX Style Guide
- 百度EFE React规范
- Khan Academy React style guide
- Pagar.me React Code Style Guide
- Redux Style Guide
Redux 风格指南
翻译自 https://redux.js.org/style-guide/style-guide/
必要的
- 不要改变 State(必须使用不可变数据)
- Reducer 函数不要有副作用。不要执行任何异步操作(Ajax、定时器、Promise),生成随机值(
Date.now()
、Math.random()
),在 Reducer 外修改变量,或者运行会影响 Reducer 作用域外的代码) - 不要将不可序列化的值放到 State 或者 Action 中(如 Promise、Symbol、Map/Set、函数、类实例等)
- 一个应用只有一个 Redux Store
强烈推荐
- 使用 Redux Toolkit 编写 Redux 逻辑
- 使用 Immer 编写不可变数据更新
- 按功能组织文件结构,一个功能的所有文件放到一个文件夹下或者一个文件中
- 尽可能将逻辑放到 Reducer 中
- 拆分的 Reducer 应该只处理自己对应的 State
- 基于 Store 数据来命名、拆分 Reducer
- 把 Reducer 看作状态机
- 标准化复杂的嵌套的/关系型状态
- 把 Action 看作事件而不是 Setter
- 编写有意义的 Action 名称
- 允许多个 Reducer 响应同一个 Action
- 避免按序发送太多的 Action
- 评估每个 State 的存放位置
- 连接更多的组件从 Store 中读取数据
- 通过
connect
使用mapDispatch
的对象简写形式 - 在函数组件中多次调用
useSelector
- 使用静态类型
- 使用 Redux DevTool 扩展来调试
- State 使用简单 JavaScript 对象
推荐
- Action 的类型写成
domain/eventName
形式 - 按照 Flux 标准 Action(Flux Standard Action,FSA)的约定编写 Action
- 使用 Action Creator
- 使用 Thunk 来处理异步逻辑
- 将复杂逻辑移到组件外部
- 使用 Selector 函数从 Store 中读取值
- 避免将表单状态放到 Redux 中
ESLint 插件
eslint-plugin-react-hooks
- react-hooks/rules-of-hooks: 包括两条规则
- 只在最顶层使用 Hook。不要在循环,条件或嵌套函数中调用 Hook
- 只在 React 函数中调用 Hook。不要在普通的 JavaScript 函数中调用 Hook
- react-hooks/exhaustive-deps: 检查副作用依赖
eslint-plugin-react
翻译自 https://github.com/yannickcr/eslint-plugin-react
React 规则
- react/boolean-prop-naming: 强制要求布尔类型的
props
命名一致(默认以is
、has
为前缀) - react/button-has-type: 防止
button
元素没有显式的type
属性 - react/default-props-match-prop-types: 强制要求所有的
defaultProps
有对应的PropType
,且定义为非必需 - react/destructuring-assignment: 强制
props
、state
、context
必须解构赋值使用 - react/display-name: 防止 React 组件定义中缺少
displayName
属性 - react/forbid-component-props: 禁止在 React 组件(非 DOM 节点)上定义某些
props
(默认className
、style
) - react/forbid-dom-props: 禁止在 DOM 节点上定义某些
props
(默认不限制) - react/forbid-elements: 禁止使用某些元素(默认不限制)
- react/forbid-foreign-prop-types: 必须通过显式
import/export
,否则禁止使用其他组件的propTypes
- react/forbid-prop-types: 禁止使用某些
propTypes
(默认为['any', 'array', 'object']
) - react/function-component-definition: 标准化函数组件定义的方式(函数表达式/函数声明/箭头函数)
- react/no-access-state-in-setstate: 防止在
this.setState
内使用this.state
- react/no-adjacent-inline-elements: 防止相邻的行内元素没有被空格隔开
- react/no-array-index-key: 防止使用数组的索引作为
key
- react/no-children-prop: 防止传递
children
作为props
- react/no-danger: 防止使用
dangerouslySetInnerHTML
作为props
- react/no-danger-with-children: 防止 DOM 元素同时使用
children
和dangerouslySetInnerHTML
- react/no-deprecated: 防止使用废弃的方法
- react/no-did-mount-set-state: 防止在
componentDidMount
中使用setState
- react/no-did-update-set-state: 防止在
componentDidUpdate
中使用setState
- react/no-direct-mutation-state: 防止直接修改
this.state
- react/no-find-dom-node: 防止使用
findDOMNode
- react/no-is-mounted: 防止使用
isMounted
- react/no-multi-comp: 防止在一个文件中定义多个组件
- react/no-redundant-should-component-update: 继承
React.PureComponent
时,防止使用shouldComponentUpdate
- react/no-render-return-value: 防止使用
ReactDOM.render
的返回值 - react/no-set-state: 防止使用
setState
- react/no-string-refs: 防止使用字符串
ref
- react/no-this-in-sfc: 防止在无状态组件中使用
this
- react/no-typos: 防止类静态属性和生命周期方法有拼写错误
- react/no-unescaped-entities: 防止 JSX 中出现未转义的 HTML 实体字符
- react/no-unknown-property: 防止使用未知的 DOM 属性
- react/no-unsafe: 防止使用不安全的生命周期方法
- react/no-unused-prop-types: 防止定义没有使用到的
propTypes
- react/no-unused-state: 防止定义没有使用到的
state
- react/no-will-update-set-state: 防止在
componentWillUpdate
中使用setState
- react/prefer-es6-class: 强制 Class 组件使用 ES6 Class 或者 ES5
create-react-class
- react/prefer-read-only-props: 强制
props
只读 - react/prefer-stateless-function: 强制无状态组件写成纯函数
- react/prop-types: 防止组件定义时缺少
PropTypes
验证 - react/react-in-jsx-scope: 防止使用 JSX 时没有引入
React
- react/require-default-props: 强制所有非必需的
props
必须定义defaultProps
- react/require-optimization: 强制 Class 组件必须实现
shouldComponentUpdate
方法 - react/require-render-return: 强制 Class 组件的
render
方法必须有返回值 - react/self-closing-comp: 防止没有子节点的组件有额外的闭合标签
- react/sort-comp: 强制组件属性、方法的书写顺序
- react/sort-prop-types: 强制
propTypes
声明按字母表顺序排序 - react/state-in-constructor: 强制类组件的
state
的初始化风格(在constructore
中或者通过 Class 属性形式初始化) - react/static-property-placement: 强制组件静态属性定义的位置(静态公共字段、静态
getter
、属性赋值) - react/style-prop-object: 强制
style
属性值是对象 - react/void-dom-elements-no-children: 防止空元素(如
img
、br
、hr
)有子节点
JSX 特定的规则
- react/jsx-boolean-value: 强制 JSX 中布尔类型属性的表示方式
- react/jsx-child-element-spacing: 强制或者不允许 JSX 中将空格定义在花括号内
- react/jsx-closing-bracket-location: 验证 JSX 中右括号的位置
- react/jsx-closing-tag-location: 验证 JSX 中闭合标签的位置
- react/jsx-curly-brace-presence: 在 JSX
props
和children
中强制使用花括号或者不允许使用没必要的花括号 - react/jsx-curly-newline: 强制 JSX 中的花括号换行风格一致
- react/jsx-curly-spacing: 强制或者不允许 JSX 中的花括号内有空格
- react/jsx-equals-spacing: 强制或者不允许 JSX 属性中的等号两边有空格
- react/jsx-filename-extension: 限制包含 JSX 的文件扩展名(默认为
.jsx
) - react/jsx-first-prop-new-line: 强制第一个属性的换行位置
- react/jsx-fragments: 强制 Fragment 使用简写或者标准形式
- react/jsx-handler-names: 强制事件处理函数的命名约定(默认属性以
on
为前缀,处理函数以handle
为前缀) - react/jsx-indent: 验证 JSX 元素的缩进
- react/jsx-indent-props: 验证 JSX
props
缩进 - react/jsx-key: 使用迭代 JSX 组件数组/集合时,检测是否缺少
key
属性 - react/jsx-max-depth: 验证 JSX 节点的最大深度
- react/jsx-max-props-per-line: 限制 JSX 中每行的
props
最大数量 - react/jsx-no-bind: 禁止在 JSX
props
中使用bind()
或箭头函数 - react/jsx-no-comment-textnodes: 防止注释被作为文本节点插入到 JSX 中(注释应该定义在花括号内)
- react/jsx-no-duplicate-props: 防止在 JSX 中使用重复的
props
属性 - react/jsx-no-literals: 禁止在 JSX 中使用字符串字面量
- react/jsx-no-script-url: 禁止使用
javascript:
URL - react/jsx-no-target-blank: 禁止使用不安全的
target='_blank'
属性 - react/jsx-no-undef: 不允许在 JSX 中使用未声明的变量
- react/jsx-no-useless-fragment: 不允许使用冗余的不必要的 Fragment
- react/jsx-one-expression-per-line: 强制 JSX 中一行只有一个表达式(JSX 元素)
- react/jsx-pascal-case: 强制用户定义的组件使用 PascalCase 命名风格
- react/jsx-props-no-multi-spaces: 不允许内联的 JSX
props
间有空格 - react/jsx-props-no-spreading: 不允许在 JSX 中使用
props
展开,显式传递props
- react/jsx-sort-default-props: 强制
defaultProps
按字母表顺序排序 - react/jsx-sort-props: 强制组件的
props
属性按字母表顺序排序 - react/jsx-space-before-closing: 验证 JSX 中闭合标签前的空格(废弃)
- react/jsx-tag-spacing: 验证 JSX 中标签内和周围的空格
- react/jsx-uses-react: 防止 React 被错误标记为未使用
- react/jsx-uses-vars: 防止 JSX 中的变量被错误标记为未使用
- react/jsx-wrap-multilines: 强制多行 JSX 使用圆括号包裹
其他 ESLint 插件
- JSX 可访问性: eslint-plugin-jsx-a11y
- React Native: eslint-plugin-react-native