Ein erfahrungsgemäß angemessener Ansatz für React und JSX
Dieser Style Guide basiert auf die aktuell vorherrschenden Javascript Standards, obwohl ein paar Konventionen (z.B. async/await oder statische Klassenvariablen) noch aufgenommen oder von Fall zu Fall verboten werden können. Derzeit ist alles, was vor der „stage 3“ liegt, weder in diesem Handbuch enthalten noch empfohlen.
- Grundregeln
- Class vs
React.createClass
vs zustandslos - Mixins
- Namensgebung
- Deklarierung
- Ausrichtung
- Anführungszeichen
- Abstände
- Props
- Refs
- Klammern
- Tags
- Methoden
- Anordnung
isMounted
- Eine Datei darf nur eine React Komponente enthalten.
- Es sind jedoch mehrere zustandslose oder „pure“ Komponenten pro Datei erlaubt. eslint:
react/no-multi-comp
.
- Es sind jedoch mehrere zustandslose oder „pure“ Komponenten pro Datei erlaubt. eslint:
- Verwende immer die JSX Syntax.
- Verwende
React.createElement
nur, wenn die App nicht aus einer JSX Datei initialisiert wird. react/forbid-prop-types
erlaubtarrays
undobjects
nur, wenn explizit angegeben wird wasarrays
undobjects
enthält, unter der Verwendung vonarrayOf
,objectOf
odershape
.
-
Bei einem internen „state“ und/oder „refs“, ist
class extends React.Component
,React.createClass
vorzuziehen. eslint:react/prefer-es6-class
react/prefer-stateless-function
// schlecht const Listing = React.createClass({ // ... render() { return <div>{this.state.hello}</div>; } }); // gut class Listing extends React.Component { // ... render() { return <div>{this.state.hello}</div>; } }
Bei keinem „state“ oder „refs“, werden normale Funktionen (keine Pfeilfunktionen) gegenüber Klassen bevorzugt:
// schlecht class Listing extends React.Component { render() { return <div>{this.props.hello}</div>; } } // schlecht (es wird abgeraten sich auf die Schlussfolgerung des Funktionsnamens zu verlassen) const Listing = ({ hello }) => ( <div>{hello}</div> ); // gut function Listing({ hello }) { return <div>{hello}</div>; }
Warum? Mixins eröffnen implizite Abhängigkeiten, versuchsachen Namenskonflikte und eine beschleunigende Komplexität. Die meisten Anwendungsfälle für Mixins lassen sich besser über Komponenten, höhere Komponenten oder Utility-Module realisieren.
-
Erweiterungen: Verwende
.jsx
Erweiterungen für React Komponenten. eslint:react/jsx-filename-extension
-
Dateiname: Verwende PascalCase für Dateinamen. Z.B.,
ReservationCard.jsx
. -
Benennung der Referenzen: Verwende PascalCase für React Komponenten und camelCase für seine Instanzen. eslint:
react/jsx-pascal-case
// schlecht import reservationCard from './ReservationCard'; // gut import ReservationCard from './ReservationCard'; // schlecht const ReservationItem = <ReservationCard />; // gut const reservationItem = <ReservationCard />;
-
Benennung der Komponenten: Verwende den Dateinamen als Komponentenname. Zum Beispiel,
ReservationCard.jsx
sollte folgenden Referenznamen habenReservationCard
. Allerdings sollte für eine Root Komponente eines Ordnersindex.jsx
als Dateiname verwendet werden und der Ordnername als Komponentenname:// schlecht import Footer from './Footer/Footer'; // schlecht import Footer from './Footer/index'; // gut import Footer from './Footer';
-
Bennenung höherer Komponenten: Verwende eine Komination vom Namen der höheren Komponente und den Namen der übergebenden Komponenten als den
displayName
der erzeugten Komponente. Zum Beispiel, wenn die höhere KomponentewithFoo()
, die KomponenteBar
übergibt, sollte eine Komponente mit einemdisplayName
vonwithFoo(Bar)
erzeugen.Warum? Der
displayName
einer Komponente könnte von Entwicklertools oder Fehlermeldungen verwendet werden und einen Wert zu haben, der klar ist und die Beziehung angibt hilft um zu verstehen was passiert.// schlecht export default function withFoo(WrappedComponent) { return function WithFoo(props) { return <WrappedComponent {...props} foo />; } } // gut 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; }
-
Bennenung der Props: Vermeide die Verwendung von DOM Komponenten Prop-Namen für verschiedene Vorhaben.
Warum? Man erwartet, wie bei
style
undclassName
, dass Props genau eine spezielle Sache bedeuten. Durch das Ändern dieser API für Untergruppen der App, wird der Code weniger lesbar und wartbar und kann Fehler verursachen.// schlecht <MyComponent style="fancy" /> // schlecht <MyComponent className="fancy" /> // gut <MyComponent variant="fancy" />
-
Verwende nicht
displayName
für die Benennung von Komponenten. Benenne stattdessen die Komponente durch die Referenz.// schlecht export default React.createClass({ displayName: 'ReservationCard', // stuff goes here }); // gut export default class ReservationCard extends React.Component { }
-
Folge diese Ausrichtungsstil für die JSX Syntax. eslint:
react/jsx-closing-bracket-location
react/jsx-closing-tag-location
// schlecht <Foo superLongParam="bar" anotherSuperLongParam="baz" /> // gut <Foo superLongParam="bar" anotherSuperLongParam="baz" /> // Wenn die Props auf eine Zeile passen, dann halte sie auf der gleichen Zeile. <Foo bar="bar" /> // Kinder werden normal eingerückt <Foo superLongParam="bar" anotherSuperLongParam="baz" > <Quux /> </Foo> // schlecht {showButton && <Button /> } // schlecht { showButton && <Button /> } // gut {showButton && ( <Button /> )} // gut {showButton && <Button />}
-
Verwende immer doppelte Anführungszeichen (
"
) für JSX Attribute aber einfache Anführungszeichen ('
) für alles andere JS. eslint:jsx-quotes
Warum? Normale HTML Attribute verwenden typischerweise auch doppelte Anführungszeichen anstatt einfache und JSX spiegelt diese Konvention wieder.
// schlecht <Foo bar='bar' /> // gut <Foo bar="bar" /> // schlecht <Foo style={{ left: "20px" }} /> // gut <Foo style={{ left: '20px' }} />
-
Füge immer ein einzelnes Leerzeichen in selbstschließendes Tag ein. eslint:
no-multi-spaces
,react/jsx-tag-spacing
// schlecht <Foo/> // sehr schlecht <Foo /> // schlecht <Foo /> // gut <Foo />
-
Fülle die geschweiften JSX-Klammern nicht mit Zwischenräumen. eslint:
react/jsx-curly-spacing
// schlecht <Foo bar={ baz } /> // gut <Foo bar={baz} />
-
Benutze immer camelCase für Props Namen.
// schlecht <Foo UserName="hello" phone_number={12345678} /> // gut <Foo userName="hello" phoneNumber={12345678} />
-
Lasse den Wert der Prop weg, wenn er immer explizit
true
ist. eslint:react/jsx-boolean-value
// schlecht <Foo hidden={true} /> // gut <Foo hidden /> // gut <Foo hidden />
-
Gebe immer ein
alt
Prop an<img>
Tags an. Wenn das Bild repräsentativ ist, kannalt
ein leerer String sein oder der<img>
Tag mussrole="presentation"
haben. eslint:jsx-a11y/alt-text
// schlecht <img src="hello.jpg" /> // gut <img src="hello.jpg" alt="Me waving hello" /> // gut <img src="hello.jpg" alt="" /> // gut <img src="hello.jpg" role="presentation" />
-
Verwende keine Wörter wie "image", "photo" oder "picture" in
<img>
alt
Props. eslint:jsx-a11y/img-redundant-alt
Warum? Screenreader geben
img
Elemente bereits als Bilder an, darum muss man diese Information nicht im alt Text mit angeben.// schlecht <img src="hello.jpg" alt="Picture of me waving hello" /> // gut <img src="hello.jpg" alt="Me waving hello" />
-
Verwende nur gültige, keine abstrakten ARIA Regeln. eslint:
jsx-a11y/aria-role
// schlecht - keine ARIA Regel <div role="datepicker" /> // schlecht - abstrakte ARIA Regel <div role="range" /> // gut <div role="button" />
-
Verwende nicht
accessKey
an Elementen. eslint:jsx-a11y/no-access-key
Warum? Inkonsistenzen zwischen Tastaturkürzeln und Tastaturbefehlen, die von Personen verwendet werden, die Screenreader und Tastaturen verwenden, erschweren die Zugänglichkeit.
// schlecht
<div accessKey="h" />
// gut
<div />
- Vermeide die Verwendung eines Array Indizes als
key
Prop, bevorzuge eine festen ID. eslint:react/no-array-index-key
Warum? Keine feste ID zu verwenden ist ein Anit-Pattern weil es die Leistung negativ beeinflussen und Probleme mit dem Komponentenzustand verursachen kann.
Wir empfehlen nicht, Indizes für Schlüssel zu verwenden, wenn sich die Reihenfolge der Elemente ändern kann.
// schlecht
{todos.map((todo, index) =>
<Todo
{...todo}
key={index}
/>
)}
// gut
{todos.map(todo => (
<Todo
{...todo}
key={todo.id}
/>
))}
- Definiere immer explizite Standard-Props für alle nicht benötigten Props.
Warum? propTypes sind eine Form der Dokumentation und durch das Anbieten von defaultProps muss der Leser des Codes keine großen Annahmen machen. Zusätzlich are a form of documentation, and providing defaultProps means the reader of your code doesn’t have to assume as much. Darüber hinaus kann es bedeuten, dass der Code bestimmte Typenprüfungen weglassen kann.
// schlecht
function SFC({ foo, bar, children }) {
return <div>{foo}{bar}{children}</div>;
}
SFC.propTypes = {
foo: PropTypes.number.isRequired,
bar: PropTypes.string,
children: PropTypes.node,
};
// gut
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,
};
- Verwende verteilte Props sparsam.
Warum? Andernfalls ist es wahrscheinlicher, dass unnötige Props an Komponenten weitergeben. Und für React v15.6.1 und älter, kannst du ungültige HTML Attribute an den DOM weitergeben.
Ausnahmen:
- Höhere Komponenten (HOC) die Proxy-Props weitergeben und propTypes hochziehen
function HOC(WrappedComponent) {
return class Proxy extends React.Component {
Proxy.propTypes = {
text: PropTypes.string,
isLoading: PropTypes.bool
};
render() {
return <WrappedComponent {...this.props} />
}
}
}
- Ausbreiten von Objekten mit bekannten, expliziten Props. Dies kann besonders nützlich sein, wenn React-Komponenten mit Mochas beforeEach-Konstrukt getestet werden.
export default function Foo {
const props = {
text: '',
isPublished: false
}
return (<div {...props} />);
}
Hinweise zur Verwendung: Filter überflüssig Props wenn möglich heraus. Verwenden auch prop-types-exact um Bugs zu verhindern.
// schlecht
render() {
const { irrelevantProp, ...relevantProps } = this.props;
return <WrappedComponent {...this.props} />
}
// gut
render() {
const { irrelevantProp, ...relevantProps } = this.props;
return <WrappedComponent {...relevantProps} />
}
-
Verwende immer Ref Callbacks. eslint:
react/no-string-refs
// schlecht <Foo ref="myRef" /> // gut <Foo ref={(ref) => { this.myRef = ref; }} />
-
Umschließe JSX Tags in Klammern, wenn sie mehr als eine Zeile umfassen. eslint:
react/jsx-wrap-multilines
// schlecht render() { return <MyComponent variant="long body" foo="bar"> <MyChild /> </MyComponent>; } // gut render() { return ( <MyComponent variant="long body" foo="bar"> <MyChild /> </MyComponent> ); } // gut, wenn einzeilig render() { const body = <div>hello</div>; return <MyComponent>{body}</MyComponent>; }
-
Bei keinen Kindern, immer selbstschließende Tags. eslint:
react/self-closing-comp
// schlecht <Foo variant="stuff"></Foo> // gut <Foo variant="stuff" />
-
Hat die Komponente mehrzeilige Eigenschaften, schließe den Tag auf einer neuen Zeile. eslint:
react/jsx-closing-bracket-location
// schlecht <Foo bar="bar" baz="baz" /> // gut <Foo bar="bar" baz="baz" />
-
Verwende Pfeilfunktionen, um lokale Variablen zu schließen.
function ItemList(props) { return ( <ul> {props.items.map((item, index) => ( <Item key={item.key} onClick={() => doSomethingWith(item.name, index)} /> ))} </ul> ); }
-
Binde Eventhandler für die Rendermethode im Konstruktor. eslint:
react/jsx-no-bind
Warum? Ein bind-Aufruf in der Render-Methode erstellt bei jedem Aufruf von Render eine neue Funktion.
// schlecht class extends React.Component { onClickDiv() { // do stuff } render() { return <div onClick={this.onClickDiv.bind(this)} />; } } // gut class extends React.Component { constructor(props) { super(props); this.onClickDiv = this.onClickDiv.bind(this); } onClickDiv() { // do stuff } render() { return <div onClick={this.onClickDiv} />; } }
-
Verwende kein Unterstrich-Präfix für interne Methoden einer React-Komponente.
Warum? Unterstich-Präfixe werden in manchen Sprachen als Konvention verwendet um etwas als privat zu kennzeichnen. Aber anders als in diesen Sprachen unterstützt JavaScript die Kennzeichnung von privat nicht nativ, alles ist öffentlich. Unabhängig von den Absichten macht das Hinzufügen eines Unterstich-Präfix die Eigenschaft nicht privat und jede Eigenschaft (mit Unterstrich-Präfix oder nicht) sollte als öffentlich behandelt werden. Siehe das folgende Problem #1024, and #490 für eine tiefere Diskussion.
// schlecht React.createClass({ _onClickSubmit() { // mache bestimmte Dinge }, // mache bestimmte Dinge }); // gut class extends React.Component { onClickSubmit() { // mache bestimmte Dinge } // mache andere Dinge }
-
Stelle sicher, dass ein Wert in der
render
Methode zurückgegeben wird. eslint:react/require-render-return
// schlecht render() { (<div />); } // gut render() { return (<div />); }
- Anordnung für
class extends React.Component
:
- Optionale
static
Methoden constructor
getChildContext
componentWillMount
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
- clickHandlers oder eventHandlers wie
onClickSubmit()
oderonChangeDescription()
- getter Methoden für
render
wiegetSelectReason()
odergetFooterContent()
- Optionale render Methods wie
renderNavigation()
oderrenderProfilePicture()
render
-
Definition von
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;
-
Anordnung von
React.createClass
: eslint:react/sort-comp
displayName
propTypes
contextTypes
childContextTypes
mixins
statics
defaultProps
getDefaultProps
getInitialState
getChildContext
componentWillMount
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
- clickHandlers oder eventHandlers wie
onClickSubmit()
oderonChangeDescription()
- getter Methods für
render
wiegetSelectReason()
odergetFooterContent()
- Optionale render Methoden wie
renderNavigation()
oderrenderProfilePicture()
render
- Verwende nicht
isMounted
. eslint:react/no-is-mounted
Warum?
isMounted
ist ein Anti-Pattern, es ist unter ES6 Klassen nicht verfügbar und es ist auf dem Weg offiziell als veraltet zu gelten.
Dieser JSX/React Style Guide ist auch in anderen Sprachen verfügbar:
Chinese (Simplified): JasonBoy/javascript
Chinese (Traditional): jigsawye/javascript
English: airbnb/javascript/react
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