iamyuu / react-style-guide

Indonesian Translation of Airbnb React/JSX Style Guide

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

    // buruk
    const Listing = React.createClass({
      // ...
      render() {
        return <div>{this.state.hello}</div>;
      }
    });
    
    // baik
    class Listing extends React.Component {
      // ...
      render() {
        return <div>{this.state.hello}</div>;
      }
    }

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

    // buruk
    class Listing extends React.Component {
      render() {
        return <div>{this.props.hello}</div>;
      }
    }
    
    // buruk (mengandalkan inferensi nama fungsi yang tidak disarankan)
    const Listing = ({ hello }) => (
      <div>{hello}</div>
    );
    
    // baik
    function Listing({ hello }) {
      return <div>{hello}</div>;
    }

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

    // buruk
    import reservationCard from './ReservationCard';
    
    // baik
    import ReservationCard from './ReservationCard';
    
    // buruk
    const ReservationItem = <ReservationCard />;
    
    // baik
    const reservationItem = <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:

    // buruk
    import Footer from './Footer/Footer';
    
    // buruk
    import Footer from './Footer/index';
    
    // baik
    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.

    // buruk
    export default function withFoo(WrappedComponent) {
      return function WithFoo(props) {
        return <WrappedComponent {...props} foo />;
      }
    }
    
    // baik
    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;
    }
  • 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.

    // buruk
    <MyComponent style="fancy" />
    
    // buruk
    <MyComponent className="fancy" />
    
    // baik
    <MyComponent variant="fancy" />

Deklarasi

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

    // buruk
    export default React.createClass({
      displayName: 'ReservationCard',
      // stuff goes here
    });
    
    // baik
    export default class ReservationCard extends React.Component {
    }

Alignment

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

    // buruk
    <Foo superLongParam="bar"
         anotherSuperLongParam="baz" />
    
    // baik
    <Foo
      superLongParam="bar"
      anotherSuperLongParam="baz"
    />
    
    // jika properti dimuat dalam satu baris maka tetap pada satu baris yang sama
    <Foo bar="bar" />
    
    // children mendapatkan indentasi secara normal
    <Foo
      superLongParam="bar"
      anotherSuperLongParam="baz"
    >
      <Quux />
    </Foo>
    
    // buruk
    {showButton &&
      <Button />
    }
    
    // buruk
    {
      showButton &&
        <Button />
    }
    
    // baik
    {showButton && (
      <Button />
    )}
    
    // baik
    {showButton && <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.

    // buruk
    <Foo bar='bar' />
    
    // baik
    <Foo bar="bar" />
    
    // buruk
    <Foo style={{ left: "20px" }} />
    
    // baik
    <Foo style={{ left: '20px' }} />

Spacing

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

    // buruk
    <Foo/>
    
    // sangat buruk
    <Foo                 />
    
    // buruk
    <Foo
     />
    
    // baik
    <Foo />
  • Jangan menyisipkan spasi didalam kurung kurawal JSX. eslint: react/jsx-curly-spacing

    // buruk
    <Foo bar={ baz } />
    
    // baik
    <Foo bar={baz} />

Props

  • Selalu gunakan camelCase untuk nama prop.

    // buruk
    <Foo
      UserName="hello"
      phone_number={12345678}
    />
    
    // baik
    <Foo
      userName="hello"
      phoneNumber={12345678}
    />
  • Hilangkan nama prop jika itu secara ekplisit bernilai true. eslint: react/jsx-boolean-value

    // buruk
    <Foo
      hidden={true}
    />
    
    // baik
    <Foo
      hidden
    />
    
    // baik
    <Foo hidden />
  • 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

    // buruk
    <img src="hello.jpg" />
    
    // baik
    <img src="hello.jpg" alt="Me waving hello" />
    
    // baik
    <img src="hello.jpg" alt="" />
    
    // baik
    <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.

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

    // buruk - not an ARIA role
    <div role="datepicker" />
    
    // buruk - abstract ARIA role
    <div role="range" />
    
    // baik
    <div role="button" />
  • 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.

// buruk
<div accessKey="h" />

// baik
<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 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.

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

// baik
{todos.map(todo => (
  <Todo
    {...todo}
    key={todo.id}
  />
))}
  • 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.

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

// baik
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,
};
  • 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
function HOC(WrappedComponent) {
  return class Proxy extends React.Component {
    Proxy.propTypes = {
      text: PropTypes.string,
      isLoading: PropTypes.bool
    };

    render() {
      return <WrappedComponent {...this.props} />
    }
  }
}
  • Spreading dengan objek yang dikenal, explicit props. Ini bisa sangat bergunakan ketika men-testing komponen React dengan Mocha's beforeEach construct.
export default function Foo {
  const props = {
    text: '',
    isPublished: false
  }

  return (<div {...props} />);
}

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

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

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

Refs

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

    // buruk
    <Foo
      ref="myRef"
    />
    
    // baik
    <Foo
      ref={(ref) => { this.myRef = ref; }}
    />

Tanda Kurung

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

    // buruk
    render() {
      return <MyComponent variant="long body" foo="bar">
               <MyChild />
             </MyComponent>;
    }
    
    // baik
    render() {
      return (
        <MyComponent variant="long body" foo="bar">
          <MyChild />
        </MyComponent>
      );
    }
    
    // baik, ketika statement hanya 1 baris
    render() {
      const body = <div>hello</div>;
      return <MyComponent>{body}</MyComponent>;
    }

Tags

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

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

    // buruk
    <Foo
      bar="bar"
      baz="baz" />
    
    // baik
    <Foo
      bar="bar"
      baz="baz"
    />

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.

    function ItemList(props) {
      return (
        <ul>
          {props.items.map((item, index) => (
            <Item
              key={item.key}
              onClick={(event) => { doSomethingWith(event, item.name, index); }}
            />
          ))}
        </ul>
      );
    }
  • 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 challenging untuk test dan men-debug, dan dapat berdampak negatif pada performance, dan karena konseptual, class fields adalah untuk data. bukan logika.

    // buruk
    class extends React.Component {
      onClickDiv() {
        // lakukan stuff
      }
    
      render() {
        return <div onClick={this.onClickDiv.bind(this)} />;
      }
    }
    
    // sangat buruk
    class extends React.Component {
      onClickDiv = () => {
        // lakukan stuff
      }
    
      render() {
        return <div onClick={this.onClickDiv} />
      }
    }
    
    // baik
    class extends React.Component {
      constructor(props) {
        super(props);
    
        this.onClickDiv = this.onClickDiv.bind(this);
      }
    
      onClickDiv() {
        // do stuff
      }
    
      render() {
        return <div onClick={this.onClickDiv} />;
      }
    }
  • 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.

    // buruk
    React.createClass({
      _onClickSubmit() {
        // lakukan stuff
      },
    
      // stuff lain
    });
    
    // baik
    class extends React.Component {
      onClickSubmit() {
        // lakukan stuff
      }
    
      // stuff lain
    }
  • Pastikan untuk mengembalikan nilai dalam method render render Anda. eslint: react/require-render-return

    // buruk
    render() {
      (<div />);
    }
    
    // baik
    render() {
      return (<div />);
    }

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...

    import React from 'react';
    import PropTypes from 'prop-types';
    
    const propTypes = {
      id: PropTypes.number.isRequired,
      url: PropTypes.string.isRequired,
      text: PropTypes.string,
    };
    
    const defaultProps = {
      text: 'Hello World',
    };
    
    class Link extends React.Component {
      static methodsAreOk() {
        return true;
      }
    
      render() {
        return <a href={this.props.url} data-id={this.props.id}>{this.props.text}</a>;
      }
    }
    
    Link.propTypes = propTypes;
    Link.defaultProps = defaultProps;
    
    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

Mengapa? isMounted is an anti-pattern, tidak tersedia saat menggunakan ES6 classes, dan sedang dalam perjalanan untuk secara resmi ditinggalkan.

Terjemahan

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

⬆ kembali ke atas

About

Indonesian Translation of Airbnb React/JSX Style Guide