Maison > outils de développement > composer > Étapes détaillées pour encapsuler React Context Composer (partage)

Étapes détaillées pour encapsuler React Context Composer (partage)

藏色散人
Libérer: 2021-12-20 13:57:25
avant
2193 Les gens l'ont consulté

Cet article est écrit par la colonne tutorielle composer pour vous présenter comment encapsuler un React Context Composer étape par étape. J'espère qu'il sera utile aux amis qui en ont besoin !

Comment encapsuler un React Context Composer étape par étape ?

Motivation

React propose de nombreuses solutions de gestion d'état, telles que Redux, Mobx, Recoil, etc. Jusqu'à présent, je n'ai expérimenté que Redux, et je pense que c'est encore un peu encombrant. Parce que j'écris habituellement beaucoup de Hooks, je préfère utiliser Context Provider avec le hook useContext, ce qui facilite la division et la combinaison d'états. Ici, nous ne discuterons pas des avantages et des inconvénients de chaque solution de gestion d’état, mais nous concentrerons sur un problème d’imbrication multicouche rencontré lors de l’utilisation de Context.

L'image ci-dessous est un code extrait d'un projet taro + react hooks + ts que j'écrivais récemment. J'ai divisé un état global (le but du fractionnement est de réduire le rendu inutile), puis je les ai imbriqués. Cette façon d’écrire me rappelle le sentiment d’être dominé par l’enfer du rappel, ce qui est très inconfortable. J'ai donc pensé à sceller moi-même un composant d'ordre élevé et à « aplatir » la structure en termes d'écriture.

<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>
Copier après la connexion

La solution la plus simple

Ici, j'ai rapidement écrit la première solution, en utilisant réduireRight pour terminer l'imbrication du fournisseur.

La raison pour laquelle réduireRight est utilisé ici au lieu de réduire est que nous sommes plus habitués à l'ordre d'écriture de la couche externe à la couche interne.

// 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>
Copier après la connexion

Après une expérience réelle, j'ai découvert que même si cela peut être utilisé, l'expérience de développement est un peu pire. Le problème est que la valeur transmise lorsque le composant entre dans le paramètre est de type any, ce qui signifie que la vérification de type statique de ts est abandonnée. Lors du passage des paramètres, étant donné que la vérification du type statique ne sera pas effectuée sur la valeur, non seulement il n'y aura pas d'invite de code lors de la saisie du code, mais cela peut également provoquer des erreurs d'exécution de niveau relativement faible. Mauvaise critique !

Un plan de transformation basé sur React.cloneElement()

Afin de transformer la solution ci-dessus, je suis tombé sur une fonction relativement impopulaire mais facile à utiliser - React.cloneElement(). Il n'y a pas beaucoup de points à noter à propos de cette fonction. Jetez principalement un œil à ses trois paramètres d'entrée. Le premier est l'élément parent, le second les accessoires parents et le troisième les paramètres restants... les enfants, à l'exception des éléments parents. premier paramètre. À part cela, toutes les autres valeurs sont facultatives.

Par exemple :

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

Ensuite, commençons la transformation. Le cadre réduireRight reste inchangé. Modifiez le type de paramètre d'entrée et le rappel réduireRight.

// 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>
Copier après la connexion

Après la transformation, lorsque nous passons des paramètres, il semble que nous créons réellement un composant (bien sûr, le composant est réellement créé, mais le composant lui-même n'est pas rendu au Dom virtuel, et ce qui est réellement rendu est après en cours de copie). Dans le même temps, le problème de vérification de type statique de valeur sur lequel nous venons de nous concentrer a également été résolu.

astuces : React.cloneElement(parent,{},child) est équivalent à React.cloneElement(parent,{children:child}), savez-vous pourquoi ?

Ressources associées

Le code source a été synchronisé avec github (https://github.com/ascodelife/react-context-provider-composer).

Il a également été emballé dans l'entrepôt npm (https://www.npmjs.com/package/@ascodelife/react-context-provider-composer), bienvenue pour en faire l'expérience.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:juejin.im
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal