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.
- Aturan Dasar
- Class vs
React.createClass
vs stateless - Mixins
- Penamaan
- Deklarasi
- Alignment
- Quotes
- Spacing
- Props
- Refs
- Tanda Kurung
- Tags
- Methods
- Ordering
isMounted
- Hanya menyertakan satu React component per file.
- Namun, multiple Stateless, atau Pure, Components diizinkan per file. eslint:
react/no-multi-comp
.
- Namun, multiple Stateless, atau Pure, Components diizinkan per file. eslint:
- Selalu gunakan sintaks JSX.
- Jangan gunakan
React.createElement
kecuali Anda menginisialisasi aplikasi dari file yang bukan JSX. react/forbid-prop-types
akan memperbolehkanarrays
danobjects
hanya jika secara ekplisit ditulis dengan isiarray
danobject
, menggunakanarrayOf
,objectOf
, ataushape
.
-
Jika Anda memiliki internal state dan/atau refs, lebih baik gunakan
class extends React.Component
daripadaReact.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>; }
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.
-
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 dariReservationCard
. Namun, untuk komponen root dari direktori, menggunakanindex.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 komponenBar
harus menghasilkan komponen dengandisplayName
dariwithFoo(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
danclassName
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" />
-
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 { }
-
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 />}
-
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' }} />
-
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} />
-
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 memilikirole="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} />
}
-
Selalu gunakan ref callbacks. eslint:
react/no-string-refs
// buruk <Foo ref="myRef" /> // baik <Foo ref={(ref) => { this.myRef = ref; }} />
-
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>; }
-
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" />
-
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 for
class extends React.Component
:
- metode
static
opsional constructor
getChildContext
componentWillMount
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
- clickHandlers atau eventHandlers seperti
onClickSubmit()
atauonChangeDescription()
- getter methods untuk
render
sepertigetSelectReason()
ataugetFooterContent()
- optional render methods seperti
renderNavigation()
ataurenderProfilePicture()
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
displayName
propTypes
contextTypes
childContextTypes
mixins
statics
defaultProps
getDefaultProps
getInitialState
getChildContext
componentWillMount
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
- clickHandlers or eventHandlers seperti
onClickSubmit()
atauonChangeDescription()
- getter methods for
render
sepertigetSelectReason()
ataugetFooterContent()
- optional render methods seperti
renderNavigation()
ataurenderProfilePicture()
render
- Jangan gunakan
isMounted
. eslint:react/no-is-mounted
Mengapa?
isMounted
is an anti-pattern, tidak tersedia saat menggunakan ES6 classes, dan sedang dalam perjalanan untuk secara resmi ditinggalkan.
Panduan JSX/React style ini juga tersedia dalam bahasa lain:
- Chinese (Simplified): JasonBoy/javascript
- Chinese (Traditional): jigsawye/javascript
- Español: agrcrobles/javascript
- Japanese: mitsuruog/javascript-style-guide
- Korean: apple77y/javascript
- Polish: pietraszekl/javascript
- Portuguese: ronal2do/javascript
- Russian: leonidlebedev/javascript-airbnb
- Thai: lvarayut/javascript-style-guide
- Turkish: alioguzhan/react-style-guide
- Ukrainian: ivanzusko/javascript
- Vietnam: uetcodecamp/jsx-style-guide