Artikelverzeichnis
-
- 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
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
redux
react
Es steht nicht in direktem Zusammenhang mit , kann aber auch invue
anderen JS/TS-Projekten verwendet werdenredux
Die Bezeichnung „Statuscontainer“ ist genauer als ein Statusverwaltungstool
Schauen wir uns als nächstes einen offiziellen Fall der normalen html + js
Verwendung anredux
<!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
redux
Das Problemstate
besteht darinimmutable
, dass es nur ersetzt und nicht geändert werden kann. Sein Designkonzept stimmt mitreact
dem instate
überein , sie alle verwenden===
, um zu vergleichenstate
, ob es aktualisiert wird.redux
inreducer
muss 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?
- Hängt nicht vom Zustand der externen Umgebung ab, sondern nur von ihren Eingabeparametern – die gleiche Eingabe gibt immer die gleiche Ausgabe zurück
- 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:
- dient dem Zweck der Wiederverwendung von Code
Mangel:
- Es handelt sich um eine implizite Abhängigkeit, und implizite Abhängigkeiten gelten in React als schlecht
- Namenskonfliktproblem
- Kann nur in ReactcreateClass funktionieren, unterstützt ES6 ClassComponent nicht
- 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
- Kann in jeder Komponente, einschließlich Klassenkomponente, verwendet werden
- Das darin propagierte Prinzip der Trennung von Containerkomponenten und Displaykomponenten wurde erreicht: Separation of Concerns
Mangel
- unintuitiv, schwer zu lesen
- Namenskonflikt
- 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:
- flexibel
Mangel:
- 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ßungimport { 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:
- Es ist sehr einfach, die Logik herauszuarbeiten
- sehr einfach zu kombinieren
- sehr lesenswert
- Keine Probleme mit Namenskonflikten
Mangel
- Hook hat seine eigenen Nutzungsbeschränkungen: Es kann nur auf der obersten Ebene der Komponente und nur in der Komponente verwendet werden
- Da das Prinzip eine Schließung ist, kann es in seltenen Fällen zu unverständlichen Problemen kommen
8. Warum brauchen wir Redux-Thunk?
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. . .