Suche…


Bemerkungen

React.createClass wurde in Version 15.5 nicht mehr unterstützt und wird voraussichtlich in Version 16 entfernt . Für diejenigen, die es noch benötigen, gibt es ein Drop-In-Ersatzpaket . Beispiele, die es verwenden, sollten aktualisiert werden.

Basiskomponente

Gegeben die folgende HTML-Datei:

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>React Tutorial</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
  </head>
  <body>
    <div id="content"></div>
    <script type="text/babel" src="scripts/example.js"></script>
  </body>
</html>

Sie können eine Basiskomponente mit dem folgenden Code in einer separaten Datei erstellen:

scripts / example.js

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class FirstComponent extends Component {
  render() {
    return (
      <div className="firstComponent">
        Hello, world! I am a FirstComponent.
      </div>
    );
  }
}
ReactDOM.render(
  <FirstComponent />, // Note that this is the same as the variable you stored above
  document.getElementById('content')
);

Sie erhalten folgendes Ergebnis (beachten Sie, was sich im div#content von div#content ):

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>React Tutorial</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
  </head>
  <body>
    <div id="content">
        <div className="firstComponent">
            Hello, world! I am a FirstComponent.
        </div>
    </div>
    <script type="text/babel" src="scripts/example.js"></script>
  </body>
</html>

Komponenten verschachteln

Die Stärke von ReactJS liegt in der Fähigkeit, Komponenten verschachteln zu können. Nehmen Sie die folgenden zwei Komponenten:

var React = require('react');
var createReactClass = require('create-react-class');

var CommentList = reactCreateClass({
  render: function() {
    return (
      <div className="commentList">
        Hello, world! I am a CommentList.
      </div>
    );
  }
});

var CommentForm = reactCreateClass({
  render: function() {
    return (
      <div className="commentForm">
        Hello, world! I am a CommentForm.
      </div>
    );
  }
});

Sie können diese Komponenten in der Definition einer anderen Komponente verschachteln und darauf verweisen:

var React = require('react');
var createReactClass = require('create-react-class');

var CommentBox = reactCreateClass({
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList /> // Which was defined above and can be reused
        <CommentForm /> // Same here
      </div>
    );
  }
});

Die weitere Verschachtelung kann auf drei Arten erfolgen, die alle ihre eigenen Plätze haben.

1. Schachteln ohne Kinder

(Fortsetzung von oben)

var CommentList = reactCreateClass({
  render: function() {
    return (
      <div className="commentList">
        <ListTitle/>
        Hello, world! I am a CommentList.
      </div>
    );
  }
});

Dies ist der Stil, in dem A B und B C komponiert.

Pros

  • Einfache und schnelle Trennung von UI-Elementen
  • Je nach Zustand der übergeordneten Komponente lassen sich Requisiten einfach für Kinder injizieren

Cons

  • Weniger Einsicht in die Kompositionsarchitektur
  • Weniger Wiederverwendbarkeit

Gut wenn

  • B und C sind nur Präsentationskomponenten
  • B sollte für den Lebenszyklus von C verantwortlich sein

2. Verschachtelung mit Kindern

(Fortsetzung von oben)

var CommentBox = reactCreateClass({
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList>
            <ListTitle/> // child
        </CommentList>
        <CommentForm />
      </div>
    );
  }
});

Dies ist der Stil, in dem A aus B besteht und A B zu B anweist.

Pros

  • Besseres Komponentenlebenszyklusmanagement
  • Bessere Sichtbarkeit der Kompositionsarchitektur
  • Bessere Wiederverwendbarkeit

Cons

  • Das Einspritzen von Requisiten kann etwas teuer werden
  • Weniger Flexibilität und Kraft in untergeordneten Komponenten

Gut wenn

  • B sollte in der Zukunft oder anderswo etwas anderes als C komponieren
  • A sollte den Lebenszyklus von C steuern

B würde C mit this.props.children rendern, und es gibt keinen strukturierten Weg für B, um this.props.children , wozu diese Kinder dienen. So kann B die untergeordneten Komponenten durch das Hinzufügen zusätzlicher Requisiten bereichern, aber wenn B genau wissen muss, was sie sind, ist # 3 möglicherweise die bessere Option.

3. Verschachtelung mit Requisiten

(Fortsetzung von oben)

var CommentBox = reactCreateClass({
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList title={ListTitle}/> //prop
        <CommentForm />
      </div>
    );
  }
});

Dies ist der Stil, in dem A B und B zusammenstellt und A die Möglichkeit bietet, etwas zu übergeben, um es zu einem bestimmten Zweck zu komponieren. Strukturiertere Komposition.

Pros

  • Komposition als Merkmal
  • Einfache Validierung
  • Bessere Komposaiblilität

Cons

  • Das Einspritzen von Requisiten kann etwas teuer werden
  • Weniger Flexibilität und Kraft in untergeordneten Komponenten

Gut wenn

  • In B sind bestimmte Merkmale definiert, um etwas zu komponieren
  • B sollte nur wissen, was gerendert werden soll

Nummer 3 ist in der Regel ein Muss, um eine öffentliche Bibliothek mit Komponenten zu erstellen. Im Allgemeinen ist es jedoch eine gute Praxis, komponierbare Komponenten zu erstellen und die Kompositionsmerkmale klar zu definieren. # 1 ist am einfachsten und schnellsten, um etwas zu schaffen, das funktioniert, aber # 2 und # 3 sollten in verschiedenen Anwendungsfällen gewisse Vorteile bieten.

Komponenten erstellen

Dies ist eine Erweiterung von Basic Example:

Grundstruktur

import React, { Component } from 'react';
import { render } from 'react-dom';

class FirstComponent extends Component {
    render() {
        return (
            <div>
                Hello, {this.props.name}! I am a FirstComponent.
            </div>
        );
    }
}

render(
    <FirstComponent name={ 'User' } />,
    document.getElementById('content')
);

Das obige Beispiel wird als zustandslose Komponente bezeichnet, da es keinen Zustand enthält (im Sinne des Wortes React).

In einem solchen Fall ist es für manche Leute empfehlenswert, Stateless Functional Components zu verwenden, die auf ES6-Pfeilfunktionen basieren.

Zustandslose Funktionskomponenten

In vielen Anwendungen gibt es intelligente Komponenten, die Status enthalten, aber dumme Komponenten darstellen, die einfach Requisiten empfangen und HTML als JSX zurückgeben. Zustandslose Funktionskomponenten sind viel wiederverwendbar und wirken sich positiv auf Ihre Anwendung aus.

Sie haben 2 Hauptmerkmale:

  1. Wenn sie gerendert werden, erhalten sie ein Objekt mit allen übergebenen Requisiten
  2. Sie müssen den JSX zurückgeben, um gerendert zu werden
// When using JSX inside a module you must import React
import React from 'react';
import PropTypes from 'prop-types';

const FirstComponent = props => (
    <div>
        Hello, {props.name}! I am a FirstComponent.
    </div>
);

//arrow components also may have props validation
FirstComponent.propTypes = {
    name: PropTypes.string.isRequired,
}

// To use FirstComponent in another file it must be exposed through an export call:
export default FirstComponent;

Stateful-Komponenten

Im Gegensatz zu den oben gezeigten 'statuslosen' Komponenten weisen 'stateful'-Komponenten ein setState , das mit der setState Methode aktualisiert werden kann. Der Status muss im constructor initialisiert werden, bevor er gesetzt werden kann:

import React, { Component } from 'react';

class SecondComponent extends Component {
    constructor(props) {
        super(props);

        this.state = {
            toggle: true
        };

        // This is to bind context when passing onClick as a callback
        this.onClick = this.onClick.bind(this);
    }

    onClick() {
        this.setState((prevState, props) => ({
            toggle: !prevState.toggle
        }));
    }
    
    render() {
        return (
            <div onClick={this.onClick}>
                Hello, {this.props.name}! I am a SecondComponent.
                <br />
                Toggle is: {this.state.toggle}
            </div>
        );
    }
}

Durch das Erweitern einer Komponente mit PureComponent anstelle von Component wird die Lebenszyklusmethode " shouldComponentUpdate() " mit einem Vergleich der shouldComponentUpdate() flache Requisiten und shouldComponentUpdate() automatisch implementiert. Dadurch bleibt Ihre Anwendung leistungsfähiger, da weniger unnötige Renderings ausgeführt werden. Dies setzt voraus, dass Ihre Komponenten "Pure" sind und immer dieselbe Ausgabe mit demselben Status und Requisiteingang wiedergeben.

Komponenten höherer Ordnung

Komponenten höherer Ordnung (HOC) ermöglichen die gemeinsame Nutzung der Komponentenfunktionalität.

import React, { Component } from 'react';

const PrintHello = ComposedComponent => class extends Component {
    onClick() {
        console.log('hello');
    }
    
    /* The higher order component takes another component as a parameter 
    and then renders it with additional props */
    render() {
        return <ComposedComponent {...this.props } onClick={this.onClick} />
    }
}

const FirstComponent = props => (
    <div onClick={ props.onClick }>
        Hello, {props.name}! I am a FirstComponent.
    </div>
);

const ExtendedComponent = PrintHello(FirstComponent);

Komponenten höherer Ordnung werden verwendet, wenn Sie die Logik für mehrere Komponenten gemeinsam nutzen möchten, unabhängig davon, wie unterschiedlich sie dargestellt werden.

setState-Fallstricke

Vorsicht ist geboten, wenn Sie setState in einem asynchronen Kontext verwenden. Sie könnten beispielsweise versuchen, setState im Callback einer Get-Anforderung setState :

class MyClass extends React.Component {
    constructor() {
        super();

        this.state = {
            user: {}
        };
    }

    componentDidMount() {
        this.fetchUser();
    }

    fetchUser() {
        $.get('/api/users/self')
            .then((user) => {
                this.setState({user: user});
            });
    }

    render() {
        return <h1>{this.state.user}</h1>;
    }
}

Dies kann zu Problemen führen. Wenn der Rückruf nach dem this.setState der Component this.setState wird, ist this.setState keine Funktion. Wenn dies der Fall ist, sollten Sie darauf achten, dass setState .

In diesem Beispiel möchten Sie möglicherweise die XHR-Anforderung abbrechen, wenn die Komponente abgemeldet wird:

class MyClass extends React.Component {
    constructor() {
        super();

        this.state = {
            user: {},
            xhr: null
        };
    }

    componentWillUnmount() {
        let xhr = this.state.xhr;

        // Cancel the xhr request, so the callback is never called
        if (xhr && xhr.readyState != 4) {
            xhr.abort();
        }
    }

    componentDidMount() {
        this.fetchUser();
    }

    fetchUser() {
        let xhr = $.get('/api/users/self')
            .then((user) => {
                this.setState({user: user});
            });

        this.setState({xhr: xhr});
    }
}

Die async-Methode wird als Status gespeichert. In componentWillUnmount Sie alle Bereinigungen durch, einschließlich des Abbruchs der XHR-Anforderung.

Sie könnten auch etwas komplexeres machen. In diesem Beispiel erstelle ich eine 'stateSetter'-Funktion, die das this-Objekt als Argument akzeptiert und this.setState verhindert, wenn die Funktion cancel aufgerufen wurde:

function stateSetter(context) {
    var cancelled = false;
    return {
        cancel: function () {
            cancelled = true;
        },
        setState(newState) {
            if (!cancelled) {
                context.setState(newState);
            }
        }
    }
}

class Component extends React.Component {
    constructor(props) {
        super(props);
        this.setter = stateSetter(this);
        this.state = {
            user: 'loading'
        };
    }
    componentWillUnmount() {
        this.setter.cancel();
    }
    componentDidMount() {
        this.fetchUser();
    }
    fetchUser() {
        $.get('/api/users/self')
            .then((user) => {
                this.setter.setState({user: user});
            });
    }
    render() {
        return <h1>{this.state.user}</h1>
    }
}

Dies funktioniert, weil die cancelled Variable in dem setState uns erstellten setState Abschluss sichtbar ist.

Requisiten

Requisiten sind eine Möglichkeit, Informationen an eine React-Komponente zu übergeben. Sie können einen beliebigen Typ haben, einschließlich Funktionen - manchmal auch als Rückrufe bezeichnet.

In JSX werden Requisiten mit der Attributsyntax übergeben

<MyComponent userID={123} />

Innerhalb der Definition für MyComponent kann jetzt auf das Benutzerobjekt zugegriffen werden

// The render function inside MyComponent
render() {
    return (
        <span>The user's ID is {this.props.userID}</span>
    )
}

Es ist wichtig, alle props , ihre Typen und gegebenenfalls ihren Standardwert zu definieren:

// defined at the bottom of MyComponent
MyComponent.propTypes = {
    someObject: React.PropTypes.object,
    userID: React.PropTypes.number.isRequired,
    title: React.PropTypes.string
};

MyComponent.defaultProps = {
    someObject: {},
    title: 'My Default Title'
}

In diesem Beispiel ist die someObject optional, aber die userID der userID ist erforderlich. Wenn Sie userID keine userID MyComponent , zeigt das React- userID zur Laufzeit eine Konsole an, die userID darauf MyComponent , dass die erforderliche Eigenschaft nicht bereitgestellt wurde. Achtung, diese Warnung wird nur in der Entwicklungsversion der React-Bibliothek angezeigt. Die Produktionsversion protokolliert keine Warnungen.

Die Verwendung von defaultProps ermöglicht Ihnen die Vereinfachung

const { title = 'My Default Title' } = this.props;
console.log(title);

zu

console.log(this.props.title);

Es ist auch ein Schutz für die Verwendung von object - functions array und functions . Wenn Sie keine Standard-Requisite für ein Objekt angeben, wird Folgendes ausgegeben, wenn die Requisite nicht übergeben wird:

if (this.props.someObject.someKey)

In obigem Beispiel ist this.props.someObject undefined und daher wird bei der Prüfung von someKey ein Fehler someKey , und der Code wird someKey . Mit defaultProps Sie die oben genannte Prüfung sicher verwenden.

Komponentenzustände - Dynamische Benutzeroberfläche

Angenommen, wir möchten das folgende Verhalten haben - Wir haben eine Überschrift (zum Beispiel ein h3-Element), und wenn Sie darauf klicken, möchten wir, dass es ein Eingabefeld wird, damit wir den Namen der Überschrift ändern können. React macht dies sehr einfach und intuitiv, indem Komponentenzustände und if-else-Anweisungen verwendet werden. (Code-Erklärung unten)

// I have used ReactBootstrap elements. But the code works with regular html elements also
var Button = ReactBootstrap.Button;
var Form = ReactBootstrap.Form;
var FormGroup = ReactBootstrap.FormGroup;
var FormControl = ReactBootstrap.FormControl;

var Comment = reactCreateClass({
  getInitialState: function() {
    return {show: false, newTitle: ''};
  },

  handleTitleSubmit: function() {
     //code to handle input box submit - for example, issue an ajax request to change name in database
  },

  handleTitleChange: function(e) {
    //code to change the name in form input box. newTitle is initialized as empty string. We need to update it with the string currently entered by user in the form
    this.setState({newTitle: e.target.value});
  },

  changeComponent: function() {
    // this toggles the show variable which is used  for dynamic UI
    this.setState({show: !this.state.show)};
  },

  render: function() {

    var clickableTitle;

    if(this.state.show) {
        clickableTitle = <Form inline onSubmit={this.handleTitleSubmit}>
                             <FormGroup controlId="formInlineTitle">
                                 <FormControl type="text" onChange={this.handleTitleChange}>
                             </FormGroup>
                         </Form>;
    } else {
        clickabletitle = <div>
                            <Button bsStyle="link" onClick={this.changeComponent}>
                                <h3> Default Text </h3>
                            </Button>
                         </div>;
    }

    return (
        <div className="comment">
            {clickableTitle}
        </div>
    );
  }
});

ReactDOM.render(
    <Comment />, document.getElementById('content')
);

Der Hauptteil des Codes ist die Variable clickableTitle . Basierend auf der Zustandsvariablen show kann es sich entweder um ein Formularelement oder um ein Button-Element handeln. Reakt ermöglicht das Verschachteln von Komponenten.

Wir können also ein {clickableTitle} -Element in die Renderfunktion einfügen. Es sucht nach der Variable clickableTitle. Basierend auf dem Wert 'this.state.show' wird das entsprechende Element angezeigt.

Variationen zustandsloser Funktionskomponenten

const languages = [
  'JavaScript',
  'Python',
  'Java',
  'Elm',
  'TypeScript',
  'C#',
  'F#'
]

// one liner
const Language = ({language}) => <li>{language}</li>

Language.propTypes = {
  message: React.PropTypes.string.isRequired
}

/**
* If there are more than one line.
* Please notice that round brackets are optional here,
* However it's better to use them for readability
*/
const LanguagesList = ({languages}) => {
  <ul>
    {languages.map(language => <Language language={language} />)}
  </ul>
}

LanguagesList.PropTypes = {
  languages: React.PropTypes.array.isRequired
}

/**
 * This syntax is used if there are more work beside just JSX presentation
 * For instance some data manipulations needs to be done.
 * Please notice that round brackets after return are required,
 * Otherwise return will return nothing (undefined)
 */
const LanguageSection = ({header, languages}) => {
  // do some work
  const formattedLanguages = languages.map(language => language.toUpperCase())
  return (
    <fieldset>
      <legend>{header}</legend>
      <LanguagesList languages={formattedLanguages} />
    </fieldset>
  )
}

LanguageSection.PropTypes = {
  header: React.PropTypes.string.isRequired,
  languages: React.PropTypes.array.isRequired
}

ReactDOM.render(
  <LanguageSection 
    header="Languages" 
    languages={languages} />,
  document.getElementById('app')
)

Hier finden Sie ein Arbeitsbeispiel davon.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow