项目作者: agusID

项目描述 :
:book: Airbnb React/JSX Style Guide
高级语言:
项目地址: git://github.com/agusID/react-style-guide.git
创建时间: 2019-10-12T10:13:47Z
项目社区:https://github.com/agusID/react-style-guide

开源协议:

下载


Panduan Airbnb React/JSX Style

Pendekatan yang sebagian besar reasonable untuk React dan JSX

Panduan style guide ini sebagian besar didasarkan pada standar yang saat ini lazim di Javascript, meskipun beberapa konvensi (yaitu async/await atau static class fields) masih bisa dimasukkan atau dilarang berdasarkan kasus per kasus. Saat ini, apapun sebelum tahap ke 3 tidak termasuk atau direkomendasikan dalam panduan ini.

Daftar Isi

  1. Aturan Dasar
  2. Class vs React.createClass vs stateless
  3. Mixins
  4. Penamaan
  5. Deklarasi
  6. Alignment
  7. Quotes
  8. Spacing
  9. Props
  10. Refs
  11. Tanda Kurung
  12. Tags
  13. Methods
  14. Ordering
  15. isMounted

Aturan Dasar

  • Hanya menyertakan satu React component per file.
  • Selalu gunakan sintaks JSX.
  • Jangan gunakan React.createElement kecuali Anda menginisialisasi aplikasi dari file yang bukan JSX.
  • react/forbid-prop-types akan memperbolehkan arrays dan objects hanya jika secara ekplisit ditulis dengan isi array dan object, menggunakan arrayOf, objectOf, atau shape.

Class vs React.createClass vs stateless

  • Jika Anda memiliki internal state dan/atau refs, lebih baik gunakan class extends React.Component daripada React.createClass. eslint: react/prefer-es6-class react/prefer-stateless-function

    1. // buruk
    2. const Listing = React.createClass({
    3. // ...
    4. render() {
    5. return <div>{this.state.hello}</div>;
    6. }
    7. });
    8. // baik
    9. class Listing extends React.Component {
    10. // ...
    11. render() {
    12. return <div>{this.state.hello}</div>;
    13. }
    14. }

    Dan jika Anda tidak memiliki state atau refs, lebih baik gunakan fungsi biasa (bukan arrow functions) daripada classes:

    1. // buruk
    2. class Listing extends React.Component {
    3. render() {
    4. return <div>{this.props.hello}</div>;
    5. }
    6. }
    7. // buruk (mengandalkan inferensi nama fungsi yang tidak disarankan)
    8. const Listing = ({ hello }) => (
    9. <div>{hello}</div>
    10. );
    11. // baik
    12. function Listing({ hello }) {
    13. return <div>{hello}</div>;
    14. }

Mixins

  • Jangan gunakan mixins.

    Mengapa? Mixins memperkenalkan dependensi yang implisit, menyebabkan nama tidak sesuai, dan kompleksitas snowballing. Sebagian besar kasus untuk mixins dapat diselesaikan dengan cara yang lebih baik melalui components, higher-order components, atau utility modules.

Penamaan

  • Ekstensi: Gunakan ekstensi .jsx untuk React components. eslint: react/jsx-filename-extension
  • Nama file: Gunanakan PascalCase untuk nama file. Contoh: ReservationCard.jsx.
  • Penamaan Referensi: Gunakan PascalCase untuk React components dan camelCase untuk intances nya. eslint: react/jsx-pascal-case

    1. // buruk
    2. import reservationCard from './ReservationCard';
    3. // baik
    4. import ReservationCard from './ReservationCard';
    5. // buruk
    6. const ReservationItem = <ReservationCard ></ReservationCard>;
    7. // baik
    8. const reservationItem = <ReservationCard ></ReservationCard>;
  • Penamaan Komponen: Gunakan nama file sebagai nama komponen. Sebagai contoh, ReservationCard.jsx harus memiliki nama referensi dari ReservationCard. Namun, untuk komponen root dari direktori, menggunakan index.jsx sebagai nama file dan gunakan nama direktori sebagai nama komponen:

    1. // buruk
    2. import Footer from './Footer/Footer';
    3. // buruk
    4. import Footer from './Footer/index';
    5. // baik
    6. import Footer from './Footer';
  • Penamaan Higher-order Component: Gunakan sebuah komposit dari nama higher-order component dan nama komponen yang diteruskan sebagai displayName pada komponen yang dihasilkan. Sebagai contoh, withFoo() pada higher-order component , ketika melewati komponen Bar harus menghasilkan komponen dengan displayName dari withFoo(Bar).

    Mengapa? displayName dapat digunakan oleh developer tools atau dalam pesan error, dan memiliki nilai yang secara jelas mengungkapkan hubungan untuk membantu orang memahami apa yang terjadi.

    1. // buruk
    2. export default function withFoo(WrappedComponent) {
    3. return function WithFoo(props) {
    4. return <WrappedComponent {...props} foo ></WrappedComponent>;
    5. }
    6. }
    7. // baik
    8. export default function withFoo(WrappedComponent) {
    9. function WithFoo(props) {
    10. return <WrappedComponent {...props} foo ></WrappedComponent>;
    11. }
    12. const wrappedComponentName = WrappedComponent.displayName
    13. || WrappedComponent.name
    14. || 'Component';
    15. WithFoo.displayName = `withFoo(${wrappedComponentName})`;
    16. return WithFoo;
    17. }
  • Penamaan Props: Hindari penggunaan nama prop pada komponen DOM untuk tujuan yang berbeda.

    Mengapa? Orang akan berpikir props seperti style dan className berarti satu hal tertentu. Memvariasikan API ini untuk sebagian dari aplikasi Anda sehingga membuat kode lebih mudah dibaca dan kurang terpelihara, dan dapat menyebabkan bug.

    1. // buruk
    2. <MyComponent style="fancy" ></MyComponent>
    3. // buruk
    4. <MyComponent className="fancy" ></MyComponent>
    5. // baik
    6. <MyComponent variant="fancy" ></MyComponent>

Deklarasi

  • Jangan gunakan displayName untuk penamaai sebuah komponen. Sebagai gantinya, beri nama pada komponen dengan referensi.

    1. // buruk
    2. export default React.createClass({
    3. displayName: 'ReservationCard',
    4. // stuff goes here
    5. });
    6. // baik
    7. export default class ReservationCard extends React.Component {
    8. }

Alignment

  • Ikuti alignment styles ini untuk sintaks JSX. eslint: react/jsx-closing-bracket-location react/jsx-closing-tag-location

    1. // buruk
    2. <Foo superLongParam="bar"
    3. anotherSuperLongParam="baz" ></Foo>
    4. // baik
    5. <Foo
    6. superLongParam="bar"
    7. anotherSuperLongParam="baz"
    8. ></Foo>
    9. // jika properti dimuat dalam satu baris maka tetap pada satu baris yang sama
    10. <Foo bar="bar" ></Foo>
    11. // children mendapatkan indentasi secara normal
    12. <Foo
    13. superLongParam="bar"
    14. anotherSuperLongParam="baz"
    15. >
    16. <Quux ></Quux>
    17. </Foo>
    18. // buruk
    19. {showButton &&
    20. <Button ></Button>
    21. }
    22. // buruk
    23. {
    24. showButton &&
    25. <Button ></Button>
    26. }
    27. // baik
    28. {showButton && (
    29. <Button ></Button>
    30. )}
    31. // baik
    32. {showButton && <Button ></Button>}

Quotes

  • Selalu gunakan tanda kutip ganda (") untuk atribut JSX, tetapi tanda kutip tunggal (') untuk semua JS lainnya. eslint: jsx-quotes

    Mengapa? Atribut HTML juga biasanya menggunakan tanda kutip ganda bukan tunggal, jadi atribut JSX menggunakan ketentuan ini.

    1. // buruk
    2. <Foo bar='bar' ></Foo>
    3. // baik
    4. <Foo bar="bar" ></Foo>
    5. // buruk
    6. <Foo style={{ left: "20px" }} ></Foo>
    7. // baik
    8. <Foo style={{ left: '20px' }} ></Foo>

Spacing

  • Selalu sisipkan satu spasi di tag self-closing. eslint: no-multi-spaces, react/jsx-tag-spacing

    1. // buruk
    2. <Foo></Foo>
    3. // sangat buruk
    4. <Foo ></Foo>
    5. // buruk
    6. <Foo
    7. ></Foo>
    8. // baik
    9. <Foo ></Foo>
  • Jangan menyisipkan spasi didalam kurung kurawal JSX. eslint: react/jsx-curly-spacing

    1. // buruk
    2. <Foo bar={ baz } ></Foo>
    3. // baik
    4. <Foo bar={baz} ></Foo>

Props

  • Selalu gunakan camelCase untuk nama prop.

    1. // buruk
    2. <Foo
    3. UserName="hello"
    4. phone_number={12345678}
    5. ></Foo>
    6. // baik
    7. <Foo
    8. userName="hello"
    9. phoneNumber={12345678}
    10. ></Foo>
  • Hilangkan nama prop jika itu secara ekplisit bernilai true. eslint: react/jsx-boolean-value

    1. // buruk
    2. <Foo
    3. hidden={true}
    4. ></Foo>
    5. // baik
    6. <Foo
    7. hidden
    8. ></Foo>
    9. // baik
    10. <Foo hidden ></Foo>
  • Selalu sertakan alt prop pada setiap tag <img>. Jika gambar adalah presentational, alt dapat berisi string kosong atau <img> harus memiliki role="presentation". eslint: jsx-a11y/alt-text

    1. // buruk
    2. <img src="hello.jpg" />
    3. // baik
    4. <img src="hello.jpg" alt="Me waving hello" />
    5. // baik
    6. <img src="hello.jpg" alt="" />
    7. // baik
    8. <img src="hello.jpg" role="presentation" />
  • Jangan gunakan kata-kata seperti “image”, “photo”, atau “picture” di <img> alt props. eslint: jsx-a11y/img-redundant-alt

    Mengapa? Screenreaders sudah memberitahu elemen img sebagai gambar, jadi tidak perlu memberikan informasi ini didalam alt.

    1. // buruk
    2. <img src="hello.jpg" alt="Picture of me waving hello" />
    3. // baik
    4. <img src="hello.jpg" alt="Me waving hello" />
  • Gunakan yang sesuai, non-abstract ARIA roles. eslint: jsx-a11y/aria-role

    1. // buruk - not an ARIA role
    2. <div role="datepicker" ></div>
    3. // buruk - abstract ARIA role
    4. <div role="range" ></div>
    5. // baik
    6. <div role="button" ></div>
  • Jangan gunakan accessKey pada elemen. eslint: jsx-a11y/no-access-key

    Mengapa? Ketidakkonsistenan antara keyboard shortcuts dan keyboard commands yang digunakan oleh seseorang yang menggunakan screenreaders dan keyboards mempersulit aksesbilitas.

    1. // buruk
    2. <div accessKey="h" ></div>
    3. // baik
    4. <div ></div>
  • Hindari menggunakan indeks array sebagai key pada prop, disarankan menggunakan ID yang lebih stabil. eslint: react/no-array-index-key

Mengapa? Tidak menggunakan ID adalah @robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318">anti-pattern karena dapat berdampak negatif pada kinerja dan menyebabkan masalah pada component state.

Kami tidak merekomendasikan untuk menggunakan indeks sebagai keys jika urutan item dapat berubah.

  1. // buruk
  2. {todos.map((todo, index) =>
  3. <Todo
  4. {...todo}
  5. key={index}
  6. ></Todo>
  7. )}
  8. // baik
  9. {todos.map(todo => (
  10. <Todo
  11. {...todo}
  12. key={todo.id}
  13. ></Todo>
  14. ))}
  • Selalu definisikan defaultProps secara ekplisit untuk semua prop yang tidak diperlukan.

    Mengapa? propTypes adalah bentuk dokumentasi, dan menyediakan defaultProps yang berarti pembaca kode Anda tidak perlu berasumsi sebanyak itu.

    1. // buruk
    2. function SFC({ foo, bar, children }) {
    3. return <div>{foo}{bar}{children}</div>;
    4. }
    5. SFC.propTypes = {
    6. foo: PropTypes.number.isRequired,
    7. bar: PropTypes.string,
    8. children: PropTypes.node,
    9. };
    10. // baik
    11. function SFC({ foo, bar, children }) {
    12. return <div>{foo}{bar}{children}</div>;
    13. }
    14. SFC.propTypes = {
    15. foo: PropTypes.number.isRequired,
    16. bar: PropTypes.string,
    17. children: PropTypes.node,
    18. };
    19. SFC.defaultProps = {
    20. bar: '',
    21. children: null,
    22. };
  • Gunakan spread prop dengan hemat (sparingly).

    Mengapa? kalau tidak, Anda akan lebih cenderung meneruskan properti yang tidak perlu ke komponen. Dan untuk React v15.6.1 keatas, Anda dapat mem-passing atribut HTML yang tidak valid ke DOM.

    Pengecualian:

  • HOCs that proxy down props dan hoist propTypes

    1. function HOC(WrappedComponent) {
    2. return class Proxy extends React.Component {
    3. Proxy.propTypes = {
    4. text: PropTypes.string,
    5. isLoading: PropTypes.bool
    6. };
    7. render() {
    8. return <WrappedComponent {...this.props} ></WrappedComponent>
    9. }
    10. }
    11. }
  • Spreading dengan objek yang dikenal, explicit props. Ini bisa sangat bergunakan ketika men-testing komponen React dengan Mocha’s beforeEach construct.

    1. export default function Foo {
    2. const props = {
    3. text: '',
    4. isPublished: false
    5. }
    6. return (<div {...props} ></div>);
    7. }

    Catatan untuk digunakan:
    Filter prop yang tidak diperlukan jika memungkinkan. Selain itu, gunakan prop-types-exact untuk membantu mencegah bug.

    1. // buruk
    2. render() {
    3. const { irrelevantProp, ...relevantProps } = this.props;
    4. return <WrappedComponent {...this.props} ></WrappedComponent>
    5. }
    6. // baik
    7. render() {
    8. const { irrelevantProp, ...relevantProps } = this.props;
    9. return <WrappedComponent {...relevantProps} ></WrappedComponent>
    10. }

Refs

  • Selalu gunakan ref callbacks. eslint: react/no-string-refs

    1. // buruk
    2. <Foo
    3. ref="myRef"
    4. ></Foo>
    5. // baik
    6. <Foo
    7. ref={(ref) => { this.myRef = ref; }}
    8. />

Tanda Kurung

  • Bungkus tag JSX dengan tanda kurung ketika lebih dari satu baris. eslint: react/jsx-wrap-multilines

    1. // buruk
    2. render() {
    3. return <MyComponent variant="long body" foo="bar">
    4. <MyChild ></MyChild>
    5. </MyComponent>;
    6. }
    7. // baik
    8. render() {
    9. return (
    10. <MyComponent variant="long body" foo="bar">
    11. <MyChild ></MyChild>
    12. </MyComponent>
    13. );
    14. }
    15. // baik, ketika statement hanya 1 baris
    16. render() {
    17. const body = <div>hello</div>;
    18. return <MyComponent>{body}</MyComponent>;
    19. }

Tags

  • Selalu self-close tags yang tidak memiliki children. eslint: react/self-closing-comp

    1. // buruk
    2. <Foo variant="stuff"></Foo>
    3. // baik
    4. <Foo variant="stuff" ></Foo>
  • Jika komponen Anda memilki properti yang multi-line, tutup tag-nya di baris baru. eslint: react/jsx-closing-bracket-location

    1. // buruk
    2. <Foo
    3. bar="bar"
    4. baz="baz" ></Foo>
    5. // baik
    6. <Foo
    7. bar="bar"
    8. baz="baz"
    9. ></Foo>

Methods

  • Gunakan arrow functions untuk menutup variabel lokal. Ini berguna ketika Anda memberikan data tambahan ke event handler. Meskipun, pastikan mereka tidak secara masiv merusak peforma, khususnya ketika mem-passing ke komponen kustom yang mungkin meruapakan PureComponents, karena mereka akan men-trigger rerender yang mungkin tidak setiap waktu.

    1. function ItemList(props) {
    2. return (
    3. <ul>
    4. {props.items.map((item, index) => (
    5. <Item
    6. key={item.key}
    7. onClick={(event) => { doSomethingWith(event, item.name, index); }}
    8. />
    9. ))}
    10. </ul>
    11. );
    12. }
  • Bind event handlers untuk render method di constructor. eslint: react/jsx-no-bind

    Mengapa? sebuah bind call di render path membuat fungsi baru disetiap single render. Jangan gunakan arrow functions di class fields, karena itu membuat mereka @charpeni/arrow-functions-in-class-properties-might-not-be-as-great-as-we-think-3b3551c440b1">challenging untuk test dan men-debug, dan dapat berdampak negatif pada performance, dan karena konseptual, class fields adalah untuk data. bukan logika.

    1. // buruk
    2. class extends React.Component {
    3. onClickDiv() {
    4. // lakukan stuff
    5. }
    6. render() {
    7. return <div onClick={this.onClickDiv.bind(this)} ></div>;
    8. }
    9. }
    10. // sangat buruk
    11. class extends React.Component {
    12. onClickDiv = () => {
    13. // lakukan stuff
    14. }
    15. render() {
    16. return <div onClick={this.onClickDiv} ></div>
    17. }
    18. }
    19. // baik
    20. class extends React.Component {
    21. constructor(props) {
    22. super(props);
    23. this.onClickDiv = this.onClickDiv.bind(this);
    24. }
    25. onClickDiv() {
    26. // do stuff
    27. }
    28. render() {
    29. return <div onClick={this.onClickDiv} ></div>;
    30. }
    31. }
  • Jangan gunakan awalan (prefix) untuk internal methods komponen pada React.

    Mengapa? Awalan garis bawah terkadang digunakan sebagai convention dalam bahasa lain untuk menunjukan private. Tapi, tidak seperti bahasa-bahasa itu, tidak ada dukungan asli untuk private di JavaScipt, semuanya bersifat public. Terlepas dari niat Anda, menambahkan awalan garis bawah ke properti Anda sebenarnya tidak menjadikan bersifat private, dan properti apapun (underscore-prefixed atau bukan) harus diperlakukan secara public. Lihat issues #1024, dan #490 untuk diskusi yang lebih mendalam.

    1. // buruk
    2. React.createClass({
    3. _onClickSubmit() {
    4. // lakukan stuff
    5. },
    6. // stuff lain
    7. });
    8. // baik
    9. class extends React.Component {
    10. onClickSubmit() {
    11. // lakukan stuff
    12. }
    13. // stuff lain
    14. }
  • Pastikan untuk mengembalikan nilai dalam method render render Anda. eslint: react/require-render-return

    1. // buruk
    2. render() {
    3. (<div ></div>);
    4. }
    5. // baik
    6. render() {
    7. return (<div ></div>);
    8. }

Ordering

  • Ordering for class extends React.Component:
  1. metode static opsional
  2. constructor
  3. getChildContext
  4. componentWillMount
  5. componentDidMount
  6. componentWillReceiveProps
  7. shouldComponentUpdate
  8. componentWillUpdate
  9. componentDidUpdate
  10. componentWillUnmount
  11. clickHandlers atau eventHandlers seperti onClickSubmit() atau onChangeDescription()
  12. getter methods untuk render seperti getSelectReason() atau getFooterContent()
  13. optional render methods seperti renderNavigation() atau renderProfilePicture()
  14. render
  • How to define propTypes, defaultProps, contextTypes, etc…

    1. import React from 'react';
    2. import PropTypes from 'prop-types';
    3. const propTypes = {
    4. id: PropTypes.number.isRequired,
    5. url: PropTypes.string.isRequired,
    6. text: PropTypes.string,
    7. };
    8. const defaultProps = {
    9. text: 'Hello World',
    10. };
    11. class Link extends React.Component {
    12. static methodsAreOk() {
    13. return true;
    14. }
    15. render() {
    16. return <a href={this.props.url} data-id={this.props.id}>{this.props.text}</a>;
    17. }
    18. }
    19. Link.propTypes = propTypes;
    20. Link.defaultProps = defaultProps;
    21. export default Link;
  • Ordering untuk React.createClass: eslint: react/sort-comp

  1. displayName
  2. propTypes
  3. contextTypes
  4. childContextTypes
  5. mixins
  6. statics
  7. defaultProps
  8. getDefaultProps
  9. getInitialState
  10. getChildContext
  11. componentWillMount
  12. componentDidMount
  13. componentWillReceiveProps
  14. shouldComponentUpdate
  15. componentWillUpdate
  16. componentDidUpdate
  17. componentWillUnmount
  18. clickHandlers or eventHandlers seperti onClickSubmit() atau onChangeDescription()
  19. getter methods for render seperti getSelectReason() atau getFooterContent()
  20. optional render methods seperti renderNavigation() atau renderProfilePicture()
  21. render

isMounted

Terjemahan

Panduan JSX/React style ini juga tersedia dalam bahasa lain:

⬆ kembali ke atas