React 风格指南 React 风格指南 (2021)

2025-06-04

React 风格指南

React 样式指南 (2021)

React 样式指南 (2021)

src:原帖:https://github.com/airbnb/javascript/tree/master/react

我写这篇文章的目的是为了提醒大家,对于刚开始学习 React 的人来说,什么是重要的。因此,我希望收到大家的评论。

基本规则

  • 每个文件仅包含一个 React 组件。
  • 始终使用 JSX 语法。

命名

  • 列表 itemExtensions:使用.jsxReact 组件的扩展。eslint:react/jsx-filename-extension
  • Filename:用于PascalCase文件名。例如,ReservationCard.jsx
  • 参考命名PascalCase用于 React 组件及其camelCase实例。
// bad
import reservationCard from './ReservationCard';

// good
import ReservationCard from './ReservationCard';

// bad
const ReservationItem = <ReservationCard />;

// good
const reservationItem = <ReservationCard />;
Enter fullscreen mode Exit fullscreen mode
  • 组件命名:使用文件名作为组件名称。例如,ReservationCard.jsx应具有引用名称ReservationCard。但是,对于目录的根组件,请使用index.jsx作为文件名,并使用目录名称作为组件名称:
// bad
import Footer from './Footer/Footer';

// bad
import Footer from './Footer/index';

// good
import Footer from './Footer';
Enter fullscreen mode Exit fullscreen mode
  • 高阶组件命名:使用高阶组件名称和传入组件名称的组合作为displayName生成组件的 。例如,高阶组件withFoo(),当传入一个组件时,Bar应该生成一个带有 的displayName组件withFoo(Bar)

    为什么?组件displayName可能被开发者工具或错误消息使用,并且具有清晰表达这种关系的值有助于人们理解正在发生的事情。

    // bad
    export default function withFoo(WrappedComponent) {
      return function WithFoo(props) {
        return <WrappedComponent {...props} foo />;
      }
    }
    
    // good
    export default function withFoo(WrappedComponent) {
      function WithFoo(props) {
        return <WrappedComponent {...props} foo />;
      }
    
      const wrappedComponentName = WrappedComponent.displayName
        || WrappedComponent.name
        || 'Component';
    
      WithFoo.displayName = `withFoo(${wrappedComponentName})`;
      return WithFoo;
    }
    

宣言

  • 不要用它displayName来命名组件。请通过引用来命名组件。

    // bad
    export default React.createClass({
      displayName: 'ReservationCard',
      // stuff goes here
    });
    
    // good
    export default function ReservationCard(props) {
        return ()
    }
    

结盟

  • 遵循 JSX 语法的这些对齐样式。eslint:react/jsx-closing-bracket-location react/jsx-closing-tag-location

    // bad
    <Foo superLongParam="bar"
         anotherSuperLongParam="baz" />
    
    // good
    <Foo
      superLongParam="bar"
      anotherSuperLongParam="baz"
    />
    
    // if props fit in one line then keep it on the same line
    <Foo bar="bar" />
    
    // children get indented normally
    <Foo
      superLongParam="bar"
      anotherSuperLongParam="baz"
    >
      <Quux />
    </Foo>
    
    // bad
    {showButton &&
      <Button />
    }
    
    // bad
    {
      showButton &&
        <Button />
    }
    
    // good
    {showButton && (
      <Button />
    )}
    
    // good
    {showButton && <Button />}
    
    // good
    {someReallyLongConditional
      && anotherLongConditional
      && (
        <Foo
          superLongParam="bar"
          anotherSuperLongParam="baz"
        />
      )
    }
    
    // good
    {someConditional ? (
      <Foo />
    ) : (
      <Foo
        superLongParam="bar"
        anotherSuperLongParam="baz"
      />
    )}
    

道具

  • 始终使用camelCase作为 prop 名称,如果 prop 值是 React 组件,则使用 PascalCase 。

    // bad
    <Foo
      UserName="hello"
      phone_number={12345678}
    />
    
    // good
    <Foo
      userName="hello"
      phoneNumber={12345678}
      Component={SomeComponent}
    />
    
  • 当明确指定 prop 的值时,省略该值true。eslint:react/jsx-boolean-value

    // bad
    <Foo
      hidden={true}
    />
    
    // good
    <Foo
      hidden
    />
    
    // very good
    <Foo hidden />
    
  • 避免使用数组索引作为keyprop,最好使用稳定的 ID。eslint:react/no-array-index-key

为什么?不使用稳定的 ID是一种反模式,因为它会对性能产生负面影响,并导致组件状态出现问题。

如果项目的顺序可能会改变,我们不建议对键使用索引。

  // bad
  {todos.map((todo, index) =>
    <Todo
      {...todo}
      key={index}
    />
  )}

  // good
  {todos.map(todo => (
    <Todo
      {...todo}
      key={todo.id}
    />
  ))}
Enter fullscreen mode Exit fullscreen mode
  • 始终为所有非必需的 props 定义明确的 defaultProps。

为什么?propTypes 是一种文档形式,提供 defaultProps 意味着代码的读者不必做太多假设。此外,这还意味着你的代码可以省略某些类型检查。

  // bad
  function SFC({ foo, bar, children }) {
    return <div>{foo}{bar}{children}</div>;
  }
  SFC.propTypes = {
    foo: PropTypes.number.isRequired,
    bar: PropTypes.string,
    children: PropTypes.node,
  };

  // good
  function SFC({ foo, bar, children }) {
    return <div>{foo}{bar}{children}</div>;
  }
  SFC.propTypes = {
    foo: PropTypes.number.isRequired,
    bar: PropTypes.string,
    children: PropTypes.node,
  };
  SFC.defaultProps = {
    bar: '',
    children: null,
  };
Enter fullscreen mode Exit fullscreen mode
  • 谨慎使用扩展 props。> 为什么?否则,你更有可能将不必要的 props 传递给组件。对于 React v15.6.1 及更早版本,你可能会将无效的 HTML 属性传递给 DOM

例外:

  • 代理 props 并提升 propTypes 的 HOC
  function HOC(WrappedComponent) {
    return class Proxy extends React.Component {
      Proxy.propTypes = {
        text: PropTypes.string,
        isLoading: PropTypes.bool
      };

      render() {
        return <WrappedComponent {...this.props} />
      }
    }
  }
Enter fullscreen mode Exit fullscreen mode
  • 使用已知的、显式的 props 来展开对象。这在使用 Mocha 的 beforeEach 结构测试 React 组件时尤其有用。
  export default function Foo {
    const props = {
      text: '',
      isPublished: false
    }

    return (<div {...props} />);
  }
Enter fullscreen mode Exit fullscreen mode

使用说明:
尽可能过滤掉不必要的 props。此外,使用prop-types-exact有助于防止 bug。

  // bad
  render() {
    const { irrelevantProp, ...relevantProps } = this.props;
    return <WrappedComponent {...this.props} />
  }

  // good
  render() {
    const { irrelevantProp, ...relevantProps } = this.props;
    return <WrappedComponent {...relevantProps} />
  }
Enter fullscreen mode Exit fullscreen mode

参考文献

  • 始终使用 ref 回调。eslint:react/no-string-refs

    // bad
    <Foo
      ref="myRef"
    />
    
    // good
    <Foo
      ref={(ref) => { this.myRef = ref; }}
    />
    

括号

  • 当 JSX 标签跨越多行时,请将其括在括号中。eslint:react/jsx-wrap-multilines

    // bad
    render() {
      return <MyComponent variant="long body" foo="bar">
               <MyChild />
             </MyComponent>;
    }
    
    // good
    render() {
      return (
        <MyComponent variant="long body" foo="bar">
          <MyChild />
        </MyComponent>
      );
    }
    
    // good, when single line
    render() {
      const body = <div>hello</div>;
      return <MyComponent>{body}</MyComponent>;
    }
    

方法

  • 使用箭头函数来覆盖局部变量。当你需要向事件处理程序传递额外数据时,它非常方便。但是,请确保它们不会严重损害性能,尤其是在传递给可能是 PureComponents 的自定义组件时,因为它们每次都会触发可能不必要的重新渲染。

    function ItemList(props) {
      return (
        <ul>
          {props.items.map((item, index) => (
            <Item
              key={item.key}
              onClick={(event) => { doSomethingWith(event, item.name, index); }}
            />
          ))}
        </ul>
      );
    }
    
  • 在构造函数中为 render 方法绑定事件处理程序。eslint:react/jsx-no-bind

    为什么?渲染路径中的绑定调用会在每次渲染时创建一个全新的函数。不要在类字段中使用箭头函数,因为这会增加测试和调试的难度,并可能对性能产生负面影响,而且从概念上讲,类字段用于存储数据,而不是逻辑。

    // bad
    class extends React.Component {
      onClickDiv() {
        // do stuff
      }
    
      render() {
        return <div onClick={this.onClickDiv.bind(this)} />;
      }
    }
    
    // very bad
    class extends React.Component {
      onClickDiv = () => {
        // do stuff
      }
    
      render() {
        return <div onClick={this.onClickDiv} />
      }
    }
    
    // good
    class extends React.Component {
      constructor(props) {
        super(props);
    
        this.onClickDiv = this.onClickDiv.bind(this);
      }
    
      onClickDiv() {
        // do stuff
      }
    
      render() {
        return <div onClick={this.onClickDiv} />;
      }
    }
    
  • 不要对 React 组件的内部方法使用下划线前缀。

    为什么?在其他语言中,下划线前缀有时被用作表示隐私的惯例。但是,与这些语言不同,JavaScript 本身并不支持隐私,所有内容都是公开的。无论你的意图如何,在属性中添加下划线前缀并不会真正使其变为私有属性,任何属性(无论是否带有下划线前缀)都应被视为公开属性。有关更深入的讨论,请参阅问题#1024#490 。

    // bad
    React.createClass({
      _onClickSubmit() {
        // do stuff
      },
    
      // other stuff
    });
    
    // good
    class extends React.Component {
      onClickSubmit() {
        // do stuff
      }
    
      // other stuff
    }
    
  • 确保在你的render方法中返回一个值。eslint:react/require-render-return

    // bad
    render() {
      (<div />);
    }
    
    // good
    render() {
      return (<div />);
    }
    
文章来源:https://dev.to/abrahamlawson/react-style-guide-24pp
PREV
Laravel 中的管道模式
NEXT
自由职业入门指南 - 寻找高薪自由职业的热门网站