Dieser Artikel stellt hauptsächlich eine auf React Hooks basierende Lösung zur Statusfreigabe vor, führt in ihre Implementierung ein und fasst die Nutzungserfahrung zusammen, mit dem Ziel, eine zusätzliche Option für die Statusverwaltung bereitzustellen. Implementierung der Statusfreigabe basierend auf React HooksDas Teilen von Zuständen zwischen React-Komponenten ist ein häufiges Problem und es gibt viele Lösungen, wie beispielsweise Redux, MobX usw. Diese Lösungen sind sehr professionell und haben sich bewährt, ich persönlich denke jedoch, dass sie für einige weniger komplexe Projekte nicht geeignet sind und möglicherweise zusätzliche Komplexität mit sich bringen. Tatsächlich möchte ich häufig weder Mutationen noch Aktionen definieren, keine Kontextebene verwenden und keine Connect- und MapStateToProps-Befehle schreiben. Was ich möchte, ist eine leichte und einfache Lösung zum Teilen von Zuständen, die leicht zu referenzieren und zu verwenden ist. Mit der Geburt und Popularität von Hooks wurde meine Idee wahr. Als nächstes stelle ich die Lösung vor, die ich derzeit verwende. Durch die Kombination von Hooks mit dem Publish/Subscribe-Modell kann eine einfache und praktische Lösung zum Teilen von Zuständen implementiert werden. Da es nicht viel Code gibt, wird die vollständige Implementierung unten angegeben. importieren { Versenden, SetzeStateAction, benutzeCallback, Effekt verwenden, verwendenReducer, verwendenRef, verwendenState, } von „reagieren“; /** * @siehe https://github.com/facebook/react/blob/bb88ce95a87934a655ef842af776c164391131ac/packages/shared/objectIs.js * Inline-Object.is-Polyfill, um zu vermeiden, dass Verbraucher ihre eigenen versenden müssen * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is */ Funktion ist(x: beliebig, y: beliebig): boolean { Rückgabewert (x === y und (x !== 0 || 1 / x === 1 / y)) || (x !== x und y !== y); } const objectIs = typeof Object.is === 'Funktion'? Object.is: ist; /** * @siehe https://github.com/facebook/react/blob/933880b4544a83ce54c8a47f348effe725a58843/packages/shared/shallowEqual.js * Stellt Gleichheit her, indem es durch die Schlüssel eines Objekts iteriert und „false“ zurückgibt * wenn ein beliebiger Schlüssel Werte hat, deren Argumente nicht genau gleich sind. * Gibt true zurück, wenn die Werte aller Schlüssel genau gleich sind. */ Funktion flachEqual(ObjektA: beliebig, ObjektB: beliebig): Boolesch { wenn (ist(ObjektA, ObjektB)) { gibt true zurück; } Wenn ( Typ von ObjektA !== 'Objekt' || objA === null || Typ von ObjektB !== 'Objekt' || objB === null ) { gibt false zurück; } const keysA = Objekt.keys(objA); const keysB = Objekt.keys(objB); wenn (SchlüsselA.Länge !== SchlüsselB.Länge) { gibt false zurück; } // Testen Sie, ob sich die Schlüssel von A von denen von B unterscheiden. für (lass i = 0; i < SchlüsselA.Länge; i++) { Wenn ( !Object.prototype.hasOwnProperty.call(objB, SchlüsselA[i]) || !ist(ObjektA[SchlüsselA[i]], ObjektB[SchlüsselA[i]]) ) { gibt false zurück; } } gibt true zurück; } const useForceUpdate = () => useReducer(() => ({}), {})[1] als VoidFunction; Typ ISubscriber<T> = (vorherigerZustand: T, nächsterZustand: T) => void; Schnittstelle ISharedState<T> exportieren { /** Daten statisch abrufen, geeignet für die Verwendung in Nicht-Komponenten oder wenn Daten nicht an eine Ansicht gebunden sind*/ bekomme: () => T; /**Daten ändern und neuen Wert zuweisen*/ setzen: Dispatch<SetStateAction<T>>; /** (Oberflächliche) Merge-Update-Daten*/ Aktualisierung: Dispatch<Partial<T>>; /** Die Hook-Methode ruft Daten ab, die für die Verwendung in Komponenten geeignet sind. Die Komponente wird automatisch neu gerendert, wenn sich die Daten ändern*/ verwenden: () => T; /**Änderungen der Abonnementdaten */ abonnieren: (cb: ISubscriber<T>) => () => ungültig; /** Datenänderungen beim Abbestellen */ Abbestellen: (cb: ISubscriber<T>) => ungültig; /** Einige Zustände herausfiltern */ usePick<R>(picker: (status: T) => R, deps?: readonly any[]): R; } Exporttyp IReadonlyState<T> = Omit<ISharedState<T>, „set“ | „update“>; /** * Erstellen Sie einen Status, der zwischen verschiedenen Instanzen geteilt werden kann * @param initialState Anfangsdaten */ export const createSharedState = <T>(initialState: T): ISharedState<T> => { lass Zustand = Anfangszustand; const-Abonnenten: ISubscriber<T>[] = []; //Statusänderungen abonnieren const subscribe = (subscriber: ISubscriber<T>) => { Abonnenten.push(Abonnent); return () => abbestellen(Abonnent); }; // Von Statusänderungen abmelden const unsubscribe = (subscriber: ISubscriber<T>) => { const index = Abonnenten.indexOf(Abonnent); index > -1 und Abonnenten.splice(index, 1); }; // Den neuesten Stand abrufen const get = () => Status; // Status ändern const set = (next: SetStateAction<T>) => { const prevState = Status; // @ts-ignorieren const nextState = typeof next === 'Funktion' ? next(vorherigerState) : nächster; wenn (ObjektIst(Zustand, nächsterZustand)) { zurückkehren; } Zustand = nächsterZustand; Abonnenten.fürJeden((cb) => cb(vorherigerStatus, Status)); }; //Den neuesten Status der Hook-Nutzung abrufen const use = () => { const forceUpdate = useForceUpdate(); useEffect(() => { sei isMounted = true; // Aktualisieren Sie die Komponente sofort nach der Montage, um zu vermeiden, dass die ersten aktualisierten Daten nicht verwendet werden können. forceUpdate(); const un = abonnieren(() => { wenn (!isMounted) return; forceUpdate(); }); zurückgeben () => { un(); istMounted = falsch; }; }, []); Rückgabezustand; }; const usePick = <R>(picker: (s: T) => R, deps = []) => { const ref = useRef<any>({}); ref.current.picker = Auswahl; const [pickedState, setPickedState] = useState<R>(() => ref.current.picker(Status), ); ref.current.oldState = ausgewählter Status; const sub = useCallback(() => { const pickedOld = ref.current.oldState; const pickedNew = ref.current.picker(status); wenn (!shallowEqual(pickedOld, pickedNew)) { // Vermeiden Sie, dass pickedNew eine Funktion ist setPickedState(() => ausgewähltNeu); } }, []); useEffect(() => { const un = abonnieren(sub); Rückkehr un; }, []); useEffect(() => { unter(); }, [...deps]); gebe selectedState zurück; }; zurückkehren { erhalten, Satz, Aktualisierung: (Eingabe: Partial<T>) => { setze((vor) => ({ ...vor, ...Eingang, })); }, verwenden, abonnieren, abbestellen, verwendenPick, }; }; Mit createSharedState können Sie im nächsten Schritt ganz einfach einen gemeinsam genutzten Status erstellen. Auch die Verwendung in der Komponente ist sehr direkt. // Eine Statusinstanz erstellen const countState = createSharedState(0); const A = () => { //Verwenden Sie Hooks in Komponenten, um reaktionsfähige Daten zu erhalten const count = countState.use(); return <div>A: {Anzahl}</div>; }; const B = () => { //Verwende die Set-Methode, um die Daten zu ändern return <button onClick={() => countState.set(count + 1)}>Add</button>; }; const C = () => { zurückkehren ( <Schaltfläche beiKlick={() => { // Verwenden Sie die Get-Methode, um Daten abzurufen console.log(countState.get()); }} > Erhalten </button> ); }; const App = () => { zurückkehren ( <> <A /> <B /> <C /> </> ); }; Für komplexe Objekte steht außerdem eine Methode zur Verfügung, um Datenänderungen in einem angegebenen Teil der Komponente zu überwachen und so redundantes Rendering aufgrund von Änderungen in anderen Feldern zu vermeiden: const complexState = createSharedState({ eine: 0, B: { c: 0, }, }); const A = () => { const a = complexState.usePick((Zustand) => Zustand.a); Rückgabewert <div>A: {a}</div>; }; Für komplexe Objekte empfiehlt sich jedoch im Allgemeinen die Verwendung eines zusammengesetzten Ableitungsansatzes, bei dem ein komplexes Objekt aus mehreren einfachen Zuständen abgeleitet wird. Darüber hinaus benötigen wir manchmal ein Berechnungsergebnis basierend auf den Originaldaten, sodass hier auch eine Möglichkeit zum Ableiten der Daten bereitgestellt wird. Durch die explizite Deklaration von Abhängigkeiten können Sie die Datenquelle abhören und sie an die Berechnungsfunktion übergeben, um ein ansprechendes abgeleitetes Ergebnis zu erhalten. /** * Zustand abgeleitet (oder berechnet) * ```ts * const count1 = erstelleSharedState(1); * const count2 = erstelleSharedState(2); * const count3 = createDerivedState([Anzahl1, Anzahl2], ([n1, n2]) => n1 + n2); * ``` * @param-Läden * @param fn * @param Anfangswert * @returns */ Exportfunktion createDerivedState<T = any>( speichert: IReadonlyState<any>[], fn: (Werte: beliebig[]) => T, Optionen?: { /** * Ob synchron geantwortet werden soll * @default false */ synchronisieren?: Boolesch; }, ): IReadonlyState<T> & { Stopp: () => ungültig; } { const { sync } = { sync: false, ...opts }; let-Werte: any[] = stores.map((it) => it.get()); const innerModel = createSharedState<T>(fn(values)); lass versprechen: Promise<void> | null = null; const uns = stores.map((it, i) => { returniere es.subscribe((_old, newValue) => { Werte[i] = neuerWert; wenn (synchronisieren) { innerModel.set(() => fn(Werte)); zurückkehren; } // Asynchrones Update-Versprechen = Versprechen || Versprechen.auflösen().dann(() => { innerModel.set(() => fn(Werte)); Versprechen = null; }); }); }); zurückkehren { erhalten: innerModel.get, verwenden: innerModel.use, abonnieren: innerModel.subscribe, abbestellen: innerModel.unsubscribe, usePick: innerModel.usePick, Stopp: () => { uns.forEach((un) => un()); }, }; } An dieser Stelle ist die Einführung in die Implementierung der auf Hooks basierenden State-Sharing-Methode beendet. In aktuellen Projekten gibt es Szenarien, die eine Statusfreigabe erfordern, und ich habe mich für die obige Methode entschieden. Derselbe Implementierungssatz kann sowohl in Webprojekten als auch in kleinen Taro-Programmprojekten verwendet werden und verlief relativ reibungslos. BenutzererfahrungLassen Sie uns abschließend einige Merkmale dieses Ansatzes zusammenfassen: 1. Einfache Implementierung, ohne Einführung anderer Konzepte, nur kombiniert mit dem auf Hooks basierenden Publish/Subscribe-Modell und kann in React-ähnlichen Szenarien wie Taro verwendet werden; 2. Einfach zu verwenden, da es kein anderes Konzept gibt. Sie können die Statusreferenz abrufen, indem Sie die Erstellungsmethode direkt aufrufen und die Verwendungsmethode für die Statusinstanz aufrufen, um die Bindung von Komponenten und Daten abzuschließen. 3. Typfreundlich. Beim Erstellen eines Status müssen keine zusätzlichen Typen definiert werden, und der Typ kann bei der Verwendung automatisch abgeleitet werden. 4. Vermeiden Sie die „Closure-Falle“ von Hooks, da die Referenz des Status konstant ist und der neueste Wert immer über die Get-Methode des Status abgerufen werden kann: Konstanten countState = createSharedState(0); const App = () => { useEffect(() => { setzeIntervall(() => { Konsole.log(countState.get()); }, 1000); }, []); // zurückkehren ... }; 5. Unterstützt direkt die gemeinsame Nutzung zwischen mehreren React-Anwendungen. Bei Verwendung einiger Popup-Fenster ist es einfacher, mehrere React-Anwendungen zu haben: const countState = createSharedState(0); const Inhalt = () => { const count = countState.use(); gibt <div>{Anzahl}</div> zurück; }; const A = () => ( <Schaltfläche beiKlick={() => { Dialog.info({ Titel: 'Alarm', Inhalt: <Inhalt />, }); }} > offen </button> ); 6. Unterstützung beim Abrufen/Aktualisieren von Daten in Szenen außerhalb von Komponenten 7. Das SSR-Szenario weist große Einschränkungen auf: Der Status wird fragmentiert und dezentral erstellt, und der Statuslebenszyklus folgt nicht der React-Anwendung, was es unmöglich macht, SSR-Anwendungscode auf isomorphe Weise zu schreiben Das Obige ist der gesamte Inhalt dieses Artikels. Tatsächlich sind Hooks schon so lange beliebt, dass es in der Community bereits viele neue Implementierungen für die Statusfreigabe gibt. Dies dient nur als Referenz. Aufgrund der oben genannten Eigenschaften weist diese Methode offensichtliche Vorteile, aber auch schwerwiegende Mängel (für SSR) auf. Bei der tatsächlichen Verwendung kann jedoch je nach der jeweiligen Situation die geeignete Methode ausgewählt werden. Beispielsweise muss man sich bei der Applet-Anwendung von Taro2 keine Gedanken über SSR machen, deshalb bevorzuge ich diesen Ansatz. Bei einem SSR-isomorphen Projekt muss ich Redux wählen. Kurz gesagt, es gibt noch eine weitere Option, und wie diese genutzt wird, hängt von der jeweiligen Situation ab. Oben finden Sie den ausführlichen Inhalt der detaillierten Erklärung der Small State Management-Funktion basierend auf React Hooks. Weitere Informationen zur Small State Management-Funktion von React Hooks finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
<<: Implementierung des CSS Fantastic Border Animation-Effekts
>>: Aggregatabfrage- und Union-Abfragevorgänge für MySQL-Datenbanken
Installieren Sie 8.0.13 basierend auf MySQL 6.1.3...
Mit dem img-Element können wir Bilder in HTML-Dok...
Inhaltsverzeichnis Primärschlüsseleinschränkung E...
Offizielle Website von Prometheus (auch Prometheu...
Inhaltsverzeichnis Kurzbeschreibung: 1. Vier Merk...
Vorwort Bei der Entwicklung eines Gateway-Projekt...
Inhaltsverzeichnis Vorwort 1. MySQL Master-Slave-...
Früher hatte fast jede Website eine Sitemap-Seite...
In diesem Tutorial verwenden wir für die Installa...
In diesem Artikel erfahren Sie, wie Sie Excel-Dat...
Tomcat-Serverkonfiguration Jeder, der das Web ken...
Inhaltsverzeichnis 1. Übergang von der Entwicklun...
HTML-Struktur <Text> <div Klasse="W...
Dies ist die Stilempfehlung der W3C-Organisation f...
Das Gitterlayout weist einige Ähnlichkeiten mit d...