Heim  >  Artikel  >  Entwicklungswerkzeuge  >  Detaillierte Schritte zum Kapseln von React Context Composer (teilen)

Detaillierte Schritte zum Kapseln von React Context Composer (teilen)

藏色散人
藏色散人nach vorne
2021-12-20 13:57:252038Durchsuche

Dieser Artikel wurde von composerTutorial-Kolumne geschrieben, um Ihnen Schritt für Schritt vorzustellen, wie Sie einen React Context Composer kapseln. Ich hoffe, dass er Freunden, die ihn benötigen, hilfreich sein wird!

Wie kapsele ich einen React Context Composer Schritt für Schritt?

Motivation

React verfügt über viele Zustandsverwaltungslösungen wie Redux, Mobx, Recoil usw. Bisher habe ich nur Redux erlebt und finde es immer noch etwas umständlich. Da ich normalerweise viele Hooks schreibe, bevorzuge ich die Verwendung des Context Providers mit dem useContext-Hook, der das Aufteilen und Kombinieren von Zuständen erleichtert. Hier werden wir nicht die Vor- und Nachteile jeder Zustandsverwaltungslösung diskutieren, sondern uns auf ein mehrschichtiges Verschachtelungsproblem konzentrieren, das bei der Verwendung von Kontext auftritt.

Das Bild unten zeigt Code, der aus einem Taro + React Hooks + Ts-Projekt extrahiert wurde, an dem ich kürzlich geschrieben habe. Ich habe einen globalen Status aufgeteilt (der Zweck der Aufteilung besteht darin, unnötiges erneutes Rendern zu reduzieren) und sie dann verschachtelt. Diese Schreibweise erinnert mich an das Gefühl, von der Callback-Hölle beherrscht zu werden, was sehr unangenehm ist. Deshalb habe ich darüber nachgedacht, ein höherwertiges Bauteil selbst zu versiegeln und die Struktur schreibtechnisch „abzuflachen“.

<LoadingContext.Provider value={{ loading, setLoading }}>
  <UserDataContext.Provider value={{ name: "ascodelife", age: 25 }}>
    <ThemeContext.Provider value={"light"}>
    {/* ....more Providers as long as you want */}
    </ThemeContext.Provider>
  </UserDataContext.Provider>
</LoadingContext.Provider>

Die einfachste Lösung

Hier habe ich schnell die erste Lösung geschrieben und ReduceRight verwendet, um die Verschachtelung von Provider abzuschließen.

Der Grund, warum hier ReduceRight anstelle von Reduce verwendet wird, liegt darin, dass wir eher an die Schreibreihenfolge von der äußeren zur inneren Schicht gewöhnt sind.

// ContextComposer.tsx
import React from &#39;react&#39;;
type IContextComposerProps = {
  contexts: { context: React.Context<any>; value: any }[];
};
const ContextComposer: React.FC<IContextComposerProps> = ({ contexts, children }) => {
  return (
    <>
      {contexts.reduceRight((child, parent) => {
        const { context, value } = parent;
        return <context.Provider value={value}>{child}</context.Provider>;
      }, children)}
    </>
  );
};
export default ContextComposer;
// App.tsx
<ContextComposer
  contexts={[
    { context: ThemeContext, value: "light" },
    { context: UserDataContext, value: { name: "ascodelife", age: 25 } },
    { context: LoadingContext, value: { loading, setLoading } },
  ]}>
    { children }
</ContextComposer>

Nach tatsächlichen Erfahrungen habe ich festgestellt, dass die Entwicklungserfahrung zwar verwendet werden kann, aber etwas schlechter ist. Das Problem besteht darin, dass der Wert, der übergeben wird, wenn die Komponente den Parameter betritt, vom Typ „any“ ist, was bedeutet, dass die statische Typprüfung von ts aufgegeben wird. Da beim Übergeben von Parametern keine statische Typprüfung für den Wert durchgeführt wird, gibt es beim Eingeben des Codes nicht nur keine Code-Eingabeaufforderungen, sondern es kann auch zu relativ geringfügigen Laufzeitfehlern kommen. Schlechte Bewertung!

Ein Transformationsplan basierend auf React.cloneElement()

Um die obige Lösung zu transformieren, bin ich auf eine relativ unbeliebte, aber einfach zu verwendende Funktion gestoßen – React.cloneElement(). Es gibt nicht viele erwähnenswerte Punkte zu dieser Funktion. Schauen Sie sich hauptsächlich die drei Eingabeparameter an. Der erste ist das übergeordnete Element, der zweite sind die übergeordneten Requisiten und der dritte sind die verbleibenden Parameter ... untergeordnete Elemente Bis auf diesen sind alle anderen Werte optional.

Zum Beispiel:

<!-- 调用函数 -->
React.cloneElement(<div/>,{},<span/>);
<!-- 相当于创建了这样一个结构 -->
<div> 
    <span></span>
</div>

Dann starten wir die Transformation. Der ReduceRight-Frame bleibt unverändert.

// ContextComposer.tsx
import React from &#39;react&#39;;
type IContextComposerProps = {
  contexts: React.ReactElement[];
};
const ContextComposer: React.FC<IContextComposerProps> = ({ contexts, children }) => {
  return (
    <>
      {contexts.reduceRight((child, parent) => {
        return React.cloneElement(parent,{},child);
      }, children)}
    </>
  );
};
export default ContextComposer;
// App.tsx
<ContextComposer
  contexts={[
      <ThemeContext.Provider value={"light"} />,
      <UserDataContext.Provider value={{ name: "ascodelife", age: 25 }} />,
      <LoadingContext.Provider value={{ loading, setLoading }} />,
  ]}>
    { children }
</ContextComposer>

Wenn wir nach der Transformation Parameter übergeben, scheint es, als würden wir tatsächlich eine Komponente erstellen (natürlich wird die Komponente tatsächlich erstellt, aber die Komponente selbst wird nicht im virtuellen Dom gerendert, und das tatsächliche Rendering erfolgt nach dem Erstellen geklont) kopieren). Gleichzeitig wurde auch das Wertproblem der statischen Typprüfung gelöst, auf das wir uns gerade konzentriert haben.

Tipps: React.cloneElement(parent,{},child) entspricht React.cloneElement(parent,{children:child}), wissen Sie warum?

Verwandte Ressourcen

Der Quellcode wurde mit Github synchronisiert (https://github.com/ascodelife/react-context-provider-composer).

Es wurde auch im npm-Warehouse (https://www.npmjs.com/package/@ascodelife/react-context-provider-composer) gepackt, herzlich willkommen, es zu erleben.

Das obige ist der detaillierte Inhalt vonDetaillierte Schritte zum Kapseln von React Context Composer (teilen). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.im. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen