[Tatsächlicher Kampf] 9. Detaillierte React-Statusverwaltung und Redux-Mechanismus (3) – React17 + React Hook + TS4 Best Practice, Nachahmung von Jira-Projekten auf Unternehmensebene (18)


Quelle der Lerninhalte: React + React Hook + TS Best Practice – MOOC


Im Vergleich zum Original-Tutorial habe ich zu Beginn meines Studiums die neueste Version (2023.03) verwendet:

Artikel Ausführung
reagieren & reagieren-dom ^18.2.0
React-Router & React-Router-Dom ^6.11.2
antd ^4.24.8
@commitlint/cli & @commitlint/config-conventional ^17.4.4
eslint-config-prettier ^8.6.0
heiser ^8.0.3
fusselfrei ^13.1.2
hübscher 2.8.4
JSON-Server 0,17,2
craco-los ^2.0.0
@craco/craco ^7.1.0
qs ^6.11.0
dayjs ^1.11.7
Reaktionshelm ^6.1.0
@types/react-helmet ^6.1.6
Reaktionsabfrage ^6.1.0
@welldone-software/why-did-you-render ^7.0.1
@emotion/react & @emotion/styled ^11.10.6

Die spezifische Konfiguration, Bedienung und der Inhalt werden unterschiedlich sein, und auch die „Grube“ wird unterschiedlich sein. . .


1. Projektstart: Projektinitialisierung und -konfiguration

2. React- und Hook-Anwendung: Implementieren Sie die Projektliste

3. TS-Anwendung: JS God Assist – Starker Typ

4. JWT, Benutzerauthentifizierung und asynchrone Anfrage


5. CSS ist eigentlich ganz einfach: Fügen Sie Stile mit CSS-in-JS hinzu


6. Optimierung der Benutzererfahrung – Laden und Fehlerstatusbehandlung



7. Hook-, Routing- und URL-Statusverwaltung



8. Benutzerauswahl und Elementbearbeitungsfunktion


9. Detaillierte React-Statusverwaltung und Redux-Mechanismus

1&2

3&4

5. Einführung in die Redux-Nutzung

Vorhersagbarer Zustandscontainer für JavaScript-Apps – Vorhersagbarer Zustandscontainer für JavaScript-Anwendungen

  • reduxreactEs steht nicht in direktem Zusammenhang mit , kann aber auch in vueanderen JS/TS-Projekten verwendet werden
  • reduxDie Bezeichnung „Statuscontainer“ ist genauer als ein Statusverwaltungstool

Schauen wir uns als nächstes einen offiziellen Fall der normalen html + jsVerwendung anredux

Beispiele/Gegen-Vanille

<!DOCTYPE html>
<html>
  <head>
    <title>Redux basic example</title>
    <script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>
  </head>
  <body>
    <div>
      <p>
        Clicked: <span id="value">0</span> times
        <button id="increment">+</button>
        <button id="decrement">-</button>
        <button id="incrementIfOdd">Increment if odd</button>
        <button id="incrementAsync">Increment async</button>
      </p>
    </div>
    <script>
      function counter(state, action) {
    
    
        if (typeof state === 'undefined') {
    
    
          return 0
        }

        switch (action.type) {
    
    
          case 'INCREMENT':
            return state + 1
          case 'DECREMENT':
            return state - 1
          default:
            return state
        }
      }

      var store = Redux.createStore(counter)
      var valueEl = document.getElementById('value')

      function render() {
    
    
        valueEl.innerHTML = store.getState().toString()
      }

      render()
      store.subscribe(render)

      document.getElementById('increment')
        .addEventListener('click', function () {
    
    
          store.dispatch({
    
     type: 'INCREMENT' })
        })

      document.getElementById('decrement')
        .addEventListener('click', function () {
    
    
          store.dispatch({
    
     type: 'DECREMENT' })
        })

      document.getElementById('incrementIfOdd')
        .addEventListener('click', function () {
    
    
          if (store.getState() % 2 !== 0) {
    
    
            store.dispatch({
    
     type: 'INCREMENT' })
          }
        })

      document.getElementById('incrementAsync')
        .addEventListener('click', function () {
    
    
          setTimeout(function () {
    
    
            store.dispatch({
    
     type: 'INCREMENT' })
          }, 1000)
        })
    </script>
  </body>
</html>

Fühlt es sich sehr ähnlich an wie die Funktion „Use-Undo“, die ich zuvor geschrieben habe?

Vorhersehbar: Für dieselben Eingabeparameter sind der Rückgabewert der Funktion und ihre Auswirkungen sicher


Dos und Don'ts in Redux

  • reduxDas Problem statebesteht darin immutable, dass es nur ersetzt und nicht geändert werden kann. Sein Designkonzept stimmt mit reactdem in stateüberein , sie alle verwenden ===, um zu vergleichen state, ob es aktualisiert wird.
  • reduxin reducermuss eine reine Funktion sein. Dies bedeutet jedoch nicht, dass asynchrone Funktionen nicht verwendet werden können. Sie können sie im Rückruf einer asynchronen Funktion verwendendispatch

Warum nicht einfach zum Originalzustand zurückkehren, sondern ihn ersetzen?

Denn die einzige Möglichkeit, zu vergleichen, ob alle Attribute in zwei Javascript-Objekten genau gleich sind, besteht darin, einen Tiefenvergleich durchzuführen. In einer realen Anwendung ist der Code eines Tiefenvergleichs jedoch sehr groß, was viel Leistung verbraucht und erfordert Es gibt viele Vergleiche, sodass eine effektive Lösung darin besteht, vorzusehen, dass der Entwickler bei jeder Änderung ein neues Objekt zurückgibt.


Was ist eine reine Funktion?

  1. Hängt nicht vom Zustand der externen Umgebung ab, sondern nur von ihren Eingabeparametern – die gleiche Eingabe gibt immer die gleiche Ausgabe zurück
  2. Keine Nebenwirkungen – verändert die Eingabewerte der Funktion nicht und erzeugt keine beobachtbaren Nebenwirkungen wie Netzwerkanforderungen, Eingabe- und Ausgabegeräte oder Datenmutationen

6. React-Redux und HoC

Containerkomponenten werden von Präsentationskomponenten getrennt

7. [Erweitertes Lernen] Geschichte von React Hook

Das Folgende ist der Originaltext der Kursunterlagen:

Geschichte der Haken

Das React-Team hat von Anfang an großen Wert auf die Wiederverwendbarkeit des Codes von React gelegt.
.Ihre
Lösungen für die Wiederverwendbarkeit von Code sind durchgegangen: Mixin, HOC, Render Prop, bis jetzt Custom Hook.
Custom
Hook ist also kein Produkt, das aus dem Nichts geboren wurde, auch wenn viele über umfangreiche Entwicklungserfahrung in Custom Hook-Entwicklern verfügen, nicht Erfahren Sie, wie Hook entstanden ist und welche Rolle es in React spielt
.
Wenn Sie diese Designidee nicht verstehen, können Sie Custom Hook nicht tiefgreifend verstehen. Lassen Sie es uns heute gemeinsam lernen.

1. Mischen
var SetIntervalMixin = {
     
     
  componentWillMount: function() {
     
     
    this.intervals = [];
  },
  setInterval: function() {
     
     
    this.intervals.push(setInterval.apply(null, arguments));
  },
  componentWillUnmount: function() {
     
     
    this.intervals.forEach(clearInterval);
  }
};

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

var TickTock = createReactClass({
     
     
  mixins: [SetIntervalMixin], //使用mixin
  getInitialstate: function() {
     
     
    return {
     
     seconds: 0;},
  },
  componentDidMount: function() {
     
     
    this.setInterval(this.tick, 1000);//调用mixin上的方法
  }
})

Vorteil:

  1. dient dem Zweck der Wiederverwendung von Code

Mangel:

  1. Es handelt sich um eine implizite Abhängigkeit, und implizite Abhängigkeiten gelten in React als schlecht
  2. Namenskonfliktproblem
  3. Kann nur in ReactcreateClass funktionieren, unterstützt ES6 ClassComponent nicht
  4. In der Praxis zeigt sich, dass die Wartung schwierig ist
    .

Es wurde auf der offiziellen Website von React als veraltet markiert und die offizielle Beschwerde finden Sie hier.

2. HOC

Ab 2015 gab das React-Team bekannt, dass Mixin nicht empfohlen wird und jedem empfohlen wird, den HOC-Modus zu verwenden
.
HOC verwendet den „Decorator-Modus“, um Code wiederzuverwenden:

function withWindowWidth(BaseComponent) {
     
     
  class DerivedClass extends ReactComponent {
     
     
    state = {
     
     
      windowWidth: window.innerwidth,
    }
    onResize = () => {
     
     
      this.setState({
     
     
        windowWidth: window.innerwidth,
      })
    }
    componentDidMount() {
     
     
      window.addEventListener(resizethisonResize)
    }
    componentWillUnmount(){
     
     
      window.removeEventListener(resizethisonResize)
    }
    render() {
     
     ...}
  }
}

Hier beginnt die Trennung von Container-President- und Classic-Container-Komponenten.
.Das
Folgende ist der klassischste Fall der Trennung von HOC-Containerkomponenten und Präsentationskomponenten – Beispielcode für Connect in Redux:

export const createInfoScreen = (ChildComponent, fetchData, dataName) => {
     
     
  class HOComponent extends Comnonent {
     
     
    state = {
     
      counter: 0 }
    handleIncrementCounter = () => {
     
     
      this.setState({
     
      counter:this.state.counter + 1 });
    }
    componentDidMount(){
     
     
      this.props.fetchData();
    }
    render() {
     
     
      const {
     
      data={
     
     },isFetching, error } = this.props[dataName];
      if (isFetching) {
     
     
        return(
          <div>Loading</div>
        );
      }
      if (error) {
     
     
        return(
          <div>Something is wrongPlease tryagain!</div>
          ...
        )
      }
    }
  }
}

Vorteil

  1. Kann in jeder Komponente, einschließlich Klassenkomponente, verwendet werden
  2. Das darin propagierte Prinzip der Trennung von Containerkomponenten und Displaykomponenten wurde erreicht: Separation of Concerns

Mangel

  1. unintuitiv, schwer zu lesen
  2. Namenskonflikt
  3. Komponenten werden Schicht für Schicht verschachtelt
3. Requisite rendern

Seit 2017 erfreut sich Render Prop großer Beliebtheit.
.
Render Prop verwendet das „Proxy-Muster“, um Code wiederzuverwenden:

class WindowWidth extends React.Component {
     
     
  propTypes = {
     
     
    children: PropTypes.func.isRequired
  }
  state = {
     
     
    windowWidth: window.innerWidth,
  }
  onResize = () => {
     
     
    this.setState({
     
     
      windowWidth: window.innerWidth,
    })
  }
  componentDidMount() {
     
     
    window.addEventListener('resize', this.onResize);
  }
  componentWillUnmount() {
     
     
    window.removeEventListener('resize', this.onResize);
  }
  ...
 }

React Router übernimmt auch dieses API-Design:

<Route path = "/about" render= {
     
      (props) => <About {
     
     ...props} />}>

Vorteil:

  1. flexibel

Mangel:

  1. schwer zu lesen, schwer zu verstehen
4. Haken

Im Jahr 2018 kündigte das React-Team eine neue Möglichkeit zur Wiederverwendung von Code an – React Hook.
Die
wichtigste Änderung besteht darin, dass Funktionskomponenten ihren eigenen Status speichern können. Zuvor konnten Funktionskomponenten keinen eigenen Status haben.
.
Diese Änderung ermöglicht es uns, die Logik in einer React-Komponente so zu abstrahieren, als wäre es eine normale Funktion.
.Prinzip
der Umsetzung: Schließung

import {
     
      useState, useEffect } from "react";
const useWindowsWidth = () => {
     
     
  const [isScreenSmall, setIsScreenSmall] = useState(false)

  let checkScreenize = () => {
     
     
    setIsScreenSmall(window.innerWidth < 600);
  };
  useEffect(()=> {
     
     
    checkscreenSize();
    window.addEventListener("resize", checkscreenSize);
    return () => window.removeEventListener("resize", checkScreenSize);
  }, []);

  return isScreenSmall
};

export default useWindowsWidth
import React from 'react'
import useWindowWidth from'./useWindowWidth.js'

const MyComponent = () => {
     
     
  const onSmallScreen = useWindowWidth;

  return (
    // Return some elements
  )
}

Vorteil:

  1. Es ist sehr einfach, die Logik herauszuarbeiten
  2. sehr einfach zu kombinieren
  3. sehr lesenswert
  4. Keine Probleme mit Namenskonflikten

Mangel

  1. Hook hat seine eigenen Nutzungsbeschränkungen: Es kann nur auf der obersten Ebene der Komponente und nur in der Komponente verwendet werden
  2. Da das Prinzip eine Schließung ist, kann es in seltenen Fällen zu unverständlichen Problemen kommen

8. Warum brauchen wir Redux-Thunk?

reduxjs/redux-thunk: Thunk-Middleware für Redux

Kernquellcode:

import type {
    
     Action, AnyAction } from 'redux'

import type {
    
     ThunkMiddleware } from './types'

export type {
    
    
  ThunkAction,
  ThunkDispatch,
  ThunkActionDispatch,
  ThunkMiddleware
} from './types'

/** A function that accepts a potential "extra argument" value to be injected later,
 * and returns an instance of the thunk middleware that uses that value
 */
function createThunkMiddleware<
  State = any,
  BasicAction extends Action = AnyAction,
  ExtraThunkArg = undefined
>(extraArgument?: ExtraThunkArg) {
    
    
  // Standard Redux middleware definition pattern:
  // See: https://redux.js.org/tutorials/fundamentals/part-4-store#writing-custom-middleware
  const middleware: ThunkMiddleware<State, BasicAction, ExtraThunkArg> =
    ({
     
      dispatch, getState }) =>
    next =>
    action => {
    
    
      // The thunk middleware looks for any functions that were passed to `store.dispatch`.
      // If this "action" is really a function, call it and return the result.
      if (typeof action === 'function') {
    
    
        // Inject the store's `dispatch` and `getState` methods, as well as any "extra arg"
        return action(dispatch, getState, extraArgument)
      }

      // Otherwise, pass the action down the middleware chain as usual
      return next(action)
    }
  return middleware
}

export const thunk = createThunkMiddleware()

// Export the factory function so users can create a customized version
// with whatever "extra arg" they want to inject into their thunks
export const withExtraArgument = createThunkMiddleware
  • Der Versand kann in einem asynchronen Vorgang erfolgen
  • Die Verwendung von Redux-Thunk oder anderer Middleware kann asynchrone Vorgänge genauso elegant machen wie synchrone Vorgänge, und asynchrone und andere Vorgänge werden separat getrennt

Einige Referenznotizen befinden sich noch im Entwurfsstadium, also bleiben Sie dran. . .

Je suppose que tu aimes

Origine blog.csdn.net/qq_32682301/article/details/132064487
conseillé
Classement