
Inspiriert von den gelesenen Artikeln auf dem Medium, habe ich beschlossen, meinen Artikel zu schreiben und Ihnen zu erklären, wie Sie die häufigsten Fehler in Ihrer React-Anwendung vermeiden und warum Sie dies tun müssen.
Der gesamte Code ist im ES6-Stil geschrieben. Um ihn zu wiederholen, müssen Sie Babel in Ihrem Projekt verwenden (und es gibt andere, die ihn nicht verwenden?).
Ich habe versucht, jeden Fehler so detailliert wie möglich zu erklären. Daher konzentriert sich mein Artikel mehr auf junge Entwickler, die immer noch auf der Suche nach neuem Wissen sind. Obwohl es mir so scheint, kann ein erfahrener Entwickler in diesem Artikel einige interessante Dinge für sich finden.
Wenn Sie interessiert sind, dann willkommen bei cat.
In Klammern vor jedem Absatz habe ich einen Link zur Eslint-Regel hinterlassen. Sie können sie später in git finden und Ihrem Projekt hinzufügen.
(reagieren / verbieten-Komponenten-Requisiten)
Der erste häufige Fehler besteht darin, "style" und "className" als Requisiten an Ihre Komponente zu übergeben. Vermeiden Sie dies, da Sie Ihren Komponenten viel Komplexität hinzufügen.
Stattdessen können Sie die Bibliothek 'Klassennamen' verwenden und Ihrer Komponente interessante Variationen hinzufügen (wenn Sie CSS-Klassen verwenden):
const { hasError, hasBorder } = this.props; const componentClasses = classnames({ 'your-component-main-class': true, 'your-component-main-class_with-error': hasError, 'your-component-main-class_with-border': hasBorder, });
(reagieren / verbieten-Prop-Typen)
Der nächste Fehler sind keine informativen PropTypes. Verwenden Sie nicht PropTypes.any, PropTypes.array und PropTypes.object. Beschreibe deine Requisiten so detailliert wie möglich. Auf diese Weise können Sie eine gute Dokumentation für die Zukunft hinterlassen, und Sie (oder ein anderer Entwickler) werden es Ihnen oft danken.
class MyComponent extends React.Component { static propTypes = { user: PropTypes.shape({ id: PropTypes.number, name: PropTypes.string, }), policies: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.number, type: PropTypes.string, value: PropTypes.string, }), } }
(reagieren / verbieten-fremde-Requisiten-Typen)
Fahren wir mit propTypes fort. Verwenden Sie keine PropTypes einer anderen Komponente:
import SomeComponent from './SomeComponent'; SomeComponent.propTypes;
Erstellen Sie eine Datei, in der Sie Ihre globalen PropTypes in der richtigen Reihenfolge aufbewahren:
import { userShape, policiesArray } from '../common/global_prop_types';
Dies hilft babel-plugin-transform-react-remove-prop-types , propTypes aus dem Produktionscode zu entfernen und Ihre Anwendung ein wenig zu vereinfachen.
(reagieren / kein Zugriffsstatus im eingestellten Zustand)
Der folgende Fehler ist sehr interessant:
class MyComponent extends React.Component { state = { counter: 1, }; incrementCounter = () => this.setState({ counter: this.state.counter + 1 }); massIncrement = () => { // this code will lead to not what you expect this.incrementCounter(); this.incrementCounter(); } }
Da setState eine asynchrone Statusfunktion ist, ist die Statusfunktion in beiden Fällen gleich.
this.state.counter wird 1 sein und wir werden bekommen:
incrementCounter = () => this.setState({ counter: 1 + 1 }); incrementCounter = () => this.setState({ counter: 1 + 1 });
Um dies zu vermeiden, können Sie den setState-Rückruf verwenden, der den Status state als Argument empfängt:
incrementCounter = () => this.setState((prevState) => ({ counter: prevState.counter + 1 }));
(Reagieren / No-Array-Index-Schlüssel)
Dieser Fehler ist auch sehr häufig. Lesen Sie ihn daher sorgfältig durch und vermeiden Sie ihn in Zukunft:
users.map((user, index) => ( <UserComponent {...user} key={index} /> ));
React verwendet den Prop-Schlüssel als Verknüpfung zum DOM-Element, wodurch die erforderliche Komponente schnell gefunden und gerendert werden kann (alles ist natürlich komplizierter, aber ich habe es absichtlich vereinfacht).
Was passiert, wenn Sie in der Mitte des Arrays einen neuen Benutzer hinzufügen? React wird gezwungen sein, alle UserComponents nach dem Hinzufügen einer neuen neu zu rendern, da der Index für eine große Anzahl von Komponenten geändert wird. Verwenden Sie stattdessen eindeutige Schlüssel. Ein sehr einfacher Ausweg ist die ID, die Sie aus Ihrer Datenbank erhalten:
users.map((user) => ( <UserComponent {...user} key={user.id} /> ));
(reagieren / no-did-mount-set-state), (reagieren / no-did-update-set-state)
Dieser Fehler ist auch in meiner Praxis sehr häufig. Wenn Sie versuchen, den Status in der componentDidUpdate-Methode zu aktualisieren, erhalten Sie eine Endlosschleife für das erneute Rendern. React startet eine Überprüfung auf erneutes Rendern, wenn die Komponente den Status oder die Requisiten ändert. Wenn Sie den Status ändern, nachdem die Komponente im DOM bereitgestellt oder bereits aktualisiert wurde, führen Sie die Prüfung immer wieder und immer wieder aus ...
Wenn Sie den Status in componentDidMount aktualisieren, können Sie das erneute Rendern der Komponente noch einmal aufrufen, da die Funktion nach dem Mounten der Komponente im DOM einmal aufgerufen wird.
Wenn Sie die Daten nach dem Mounten der Komponente aktualisieren müssen, empfehle ich die Verwendung von Klassenvariablen:
class MyComponent extends React.Component { componentDidMount() { this.veryImportantDataThatCanBeStoredOnlyAfterMount = 'I'll be back!'; } veryImportantDataThatCanBeStoredOnlyAfterMount = void 0; render() { return <div /> } }
(reagieren / kein direkter Mutationszustand)
Die Staatsmutation ist ein sehr großer Fehler. Eine unkontrollierte Zustandsmutation führt zu nicht nachweisbaren Fehlern und infolgedessen zu großen Problemen. Meine persönliche Meinung ist , zu verwenden , die unveränderlichen-js , als eine Bibliothek, die immutabelnye Struktur hinzufügt. Und Sie können sie mit Redux / MobX / Any State Management Library verwenden. Sie können auch deepClone von lodash verwenden , um den Status zu klonen und dann den Klon zu mutieren, oder die neue JS-Funktion verwenden - Destrukturierung:
updateStateWrong = () => this.state.imRambo = true; updateStateRight = () => { const clonedState = cloneDeep(this.state); clonedState.imAGoodMan = true; this.setState(clonedState); } updateWithImmutabelJS = () => { const newState = this.state.data.set('iUseImmutableStructure', true); this.setState(data: newState); } updateWithDestructuring = () => this.setState({ ...this.state, iUseDestructuring: true });
(reagieren / bevorzugen-staatenlose-Funktion)
Diese Regel beschreibt mehr Verbesserungen Ihres Codes und Ihrer Anwendung als einen Fehler. Ich empfehle jedoch weiterhin, diese Regel zu befolgen. Wenn Ihre Komponente den Status nicht verwendet, machen Sie sie zu einer zustandslosen Komponente (ich bevorzuge den Begriff "reine Komponente"):
class MyComponentWithoutState extends React.Component { render() { return <div>I like to write a lot of unneeded code</div> } } const MyPureComponent = (props) => <div>Less code === less support</div>
(reagieren / Requisitentypen)
Bitte fügen Sie immer eine Requisitentypprüfung (propTypes) hinzu, wenn Ihre Komponente Requisiten erhält. Stellen Sie sich vor, Sie dokumentieren Ihren Code. Mehr als einmal wirst du dir dafür 'Danke' sagen (und vielleicht zu mir :)). PropTypes hilft Ihnen zu verstehen und zu verstehen, was Ihre Komponente rendern kann und was sie zum Rendern benötigt.
MyPureComponent.propTypes = { id: PropTypes.number.isRequired, // And I know that without id component will not render at all, and this is good. }
(reagieren / jsx-no-bind)
Ein sehr häufiger und großer Fehler, den ich oft im Code gesehen habe. Verwenden Sie in Jsx keine Bind- und Pfeilfunktion. Niemals. Mehr.
Der heißeste Ort in der Hölle erwartet denjenigen, der .bind (this) in JSX im Event-Handler schreibt.
Jedes Mal, wenn eine Komponente gerendert wird, wird Ihre Funktion neu erstellt, was Ihre Anwendung erheblich verlangsamen kann (dies liegt an der Tatsache, dass der Garbage Collector viel häufiger ausgeführt werden muss). Anstelle von .bind (this) können Sie die Pfeilfunktionen auf eine bestimmte Weise verwenden:
class RightWayToCallFunctionsInRender extends React.Component { handleDivClick = (event) => event; render() { return <div onClick={this.handleDivClick} /> } } const handleDivClick = (event) => event; const AndInPureComponent = () => { return <div onClick={handleDivClick} /> }
(reagieren / jsx-no-target-blank)
Sicherheitslücke. Es scheint mir sehr seltsam, dass die Leute diesen Fehler immer noch machen. Viele Leute haben 2017 viele Artikel zu diesem Thema geschrieben.
Wenn Sie einen Link mit dem Attribut target = '_ blank' erstellen, müssen Sie rel = 'noreferrer noopener' hinzufügen. Sehr einfach:
<a href="https://example.com" target="_blank" rel="noreferrer noopener" />
Danke Ihnen!
Das ist alles, was ich Ihnen im Rahmen dieses Artikels sagen möchte. Ich bin Ihnen sehr dankbar, wenn Sie, meine Leser, mir Ihr Feedback oder Ihren Kommentar hinterlassen und Ihre Meinung zu den in diesem Artikel beschriebenen Problemen mitteilen. Sie können mir auch über meine und Ihre Fehler im Code und über alles erzählen, was Sie für notwendig halten, um es zu erzählen. Nochmals vielen Dank!