Einfachere Verwaltung des Zustands mit React Hooks

Bei meiner täglichen Arbeit bei FloQast stoße ich bei der React-Entwicklung oft auf eine besondere Situation. Um CSS-Effekte auf bestimmte Komponenten umzuschalten, werde ich oft:

  • Umwandlung der funktionalen Komponente in eine Klassenkomponente und Hinzufügen eines lokalen Zustands
  • Erstellen Sie eine Komponente höherer Ordnung, wenn es eine gemeinsame Logik für mehrere Komponenten gibt.
  • Requisiten durch mehrere Komponenten zu ihren Endverbrauchern führen
  • Aktualisierungen vornehmen und Tests schreiben

Das ist eine ganze Menge.

Ich habe mich oft gefragt, ob es einen besseren Weg gibt, dies zu tun - und jetzt gibt es einen! Seit das React-Team die Version 16.8 veröffentlicht hat, können wir diese Probleme auf sehr elegante Weise mit React Hooks angehen.

Was sind React Hooks?

Laut der offiziellen Website von React sind Hooks eine neue Ergänzung in React 16.8. Mit ihnen können Sie den Zustand und andere React-Funktionen nutzen , ohne eine Klasse zu schreiben.

Aufgrund der Definition könnte Ihre erste Reaktion sein: "Werde ich nicht einfach alle meine Klassenkomponenten neu schreiben?!" React Hooks sind weit mehr als eine Umstrukturierung der gleichen React-APIs.

Lokalen Zustand zur Funktionskomponente hinzufügen

Schauen wir uns eine Schaltflächenkomponente an, wenn ein Benutzer auf sie klickt, um ihre Hintergrundfarbe zu ändern:

import React, { useState } from ‘react’;
const MyButton = () => {
   const [background, setBackground] = useState('blue');
   const btnStyle = {
      background: background
   };
   const changeBackground = () => {
     setBackground({
       background: 'green'
     });
    };
  return <Button onclick={changeBackground} style={btnStyle}>
              My Button
       </Button>;
}

Die obige Komponente hat eine einfache Zustandsvariable background um die aktuelle Hintergrundfarbe der Schaltfläche aufzuzeichnen.

Gibt es eine Möglichkeit, dies mit einer funktionalen Komponente zu tun? Ja, mit Hilfe der React Hooks useState api. Schauen wir uns an, wie wir sie in Hooks implementieren:

import React, { useState } from ‘react’;
const MyButton = () => {
   const [background, setBackground] = useState('blue');
   const btnStyle = {
      background: background
   };
   const changeBackground = () => {
     setBackground({
       background: 'green'
     });
    };
  return <Button onclick={changeBackground} style={btnStyle}>
              My Button
       </Button>;
}

Wie Sie sehen, ermöglicht die React Hooks-API lokale Zustände in funktionalen Komponenten, reduziert klassenbezogenen Boilerplate-Code und macht die funktionale Komponente dadurch leistungsfähiger.

Gemeinsame Zustandslogik extrahieren

Wenn Sie sich für die Verwendung von Hooks in zustandslosen funktionalen Komponenten entscheiden, können Sie sich auch von Boilerplate befreien. Denken Sie daran, wie oft Sie die Initialisierung von Klassenkonstruktoren und Bindungsfunktionen für Ihre Methoden geschrieben haben. Lassen Sie uns den Unterschied bei der Verwendung von Hooks sehen:

import React from 'react';
class GetTime extends React.Component {
 constructor(props) {
     super(props);
     this.state = {
        time: null
     };
  }
  checkTime() {
      this.setState({
         time: new Date()
      });
  }
  componentDidMount() {
     this.interval = setInterval(this.checkTime(), 1000);
  }
  componentWillUnMount() {
      clearInterval(this.interval);
  }
   render() {
     return <div>Current Time is: {this.state.time}</div>
  }
}

Schauen wir uns nun nachher an, indem wir Hooks:

import React, { useState, useEffect } from ‘react’;
const useTime = () => {
    const [time, setTime] = useState(null);
    useEffect(() => {
        const interval = setInterval(() => {
            setTime(new Date());
        }, 1000);
        return () => clearInterval(interval);
    }, [time]);
    return time;
}

const GetTime = () => {
    const time = useTime();
    return <div>Current Time is: {time}</div>;
}

Aus dem Vergleich geht hervor, dass es eine useTime Funktion, die die aktuelle Zeit abrufen Logik und setzt die Zeit auf eine lokale Zustandsvariable. Jetzt, jede kann die funktionale Komponente zur Anzeige der aktuellen Uhrzeit verwendet werden.

Der Nutzen von Hooks Hier vereinfachen wir den Code, indem wir die gemeinsame Zustandslogik herausnehmen.

Keine Wrapper-Hölle mehr

Werfen wir einen Blick auf eine andere Komponente:

import React from 'react';
import ReactDOM from 'react-dom';

const withCounter = Component => {
  return class ComponentWithCounter extends React.Component {
    state = {
      count: 0,
    };

    handleDecrement = () => {
      this.setState({ count: this.state.count - 1 });
    };

    handleIncrement = () => {
      this.setState({ count: this.state.count + 1 });
    };

    render() {
      const { count } = this.state;

      return (
        <Component {...this.props} count={count} onIncrease={this.handleIncrement} onDecrease={this.handleDecrement} />
      );
    }
  };
};

const App = ({ count, onIncrease, onDecrease }) => {
  return (
    <div>
      <div>Current count: {count}</div>
      <div>
        <button onClick={onDecrease}>-</button>
        <button onClick={onIncrease}>+</button>
      </div>
    </div>
  );
};

const AppWithCounter = withCounter(App);

ReactDOM.render(<AppWithCounter />, document.getElementById('root'));

Kommt Ihnen das bekannt vor? Ja, das habe ich auch schon oft gesehen.

Wie wäre es, wenn wir die obige Komponente in etwas wie das Folgende umwandeln?

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

const useCounter = () => {
  const [count, setCount] = useState(0);

  const onIncrease = () => setCount(count + 1);
  const onDecrease = () => setCount(count - 1);

  return [ count, onIncrease, onDecrease ];
};

const App = () => {
  const [ count, onIncrease, onDecrease ] = useCounter();

  return (
    <div>
      <div>Current count: {count}</div>
      <div>
        <button onClick={onDecrease}>-</button>
        <button onClick={onIncrease}>+</button>
      </div>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));

Kein Wrapper oder Klasse mit einer schönen und sauberen funktionalen Komponente Implementierung.

Erste Schritte mit React Hooks

Hooks sind in mehrfacher Hinsicht von Vorteil für uns. Sie:

  1. Ermöglichung von lokalem Zustand und Lebenszyklus in funktionalen Komponenten
  2. Extrahieren von gemeinsamer Logik in benutzerdefinierte Hooks
  3. Erhebliche Vereinfachung des Codes und Ausstieg aus der Wrapper-Hölle

Der Einstieg ist nicht schmerzhaft!

Sehen Sie? Eintreten für Hooks bedeutet nicht, dass Sie jede Klassenkomponente in Ihrer Codebasis refaktorisieren müssen. Setzen Sie sie dort ein, wo es sinnvoll ist, und schon bald werden Sie... süchtig danach sein.

Wenn Sie noch nicht überzeugt sind, finden Sie in den offiziellen Dokumenten von hooks einige gute Argumente, die Sie in Betracht ziehen können, und ich hoffe, dass meine Erfahrungen hilfreich sind.

Luyao Pan

Luyao Pan ist ein Software-Ingenieur bei FloQast. Wenn er nicht gerade programmiert, spielt Luyao gerne Tischtennis, probiert neue Gerichte aus und schaut Filme.



Zurück zu Blog