Maison > interface Web > js tutoriel > Arrêtez de faire ces erreurs de composants

Arrêtez de faire ces erreurs de composants

DDD
Libérer: 2024-11-19 10:43:03
original
936 Les gens l'ont consulté

Stop Making These Component Mistakes

La vérité est que les composants sont d'une simplicité trompeuse. Il est facile de commencer : définissez une fonction, renvoyez du JSX et arrêtez-la. Mais écrire des composants propres, maintenables et agréables à utiliser ? C’est un tout autre jeu de balle.

Sans nous en rendre compte, nous créons des composants qui sont :

  • Trop gros pour être compris d'un seul coup d'œil.
  • Péniblement difficile à tester.
  • Si étroitement couplés qu’ils sont impossibles à réutiliser.
  • Lent en raison de mauvaises décisions de performance.

Dans cet article, je vais vous expliquer les erreurs les plus courantes commises par les développeurs avec les composants React. Plus important encore, je vais vous montrer comment les réparer sans détruire l'intégralité de votre application.

Que vous débutiez ou que vous ayez des années d'expérience, ces conseils vous aideront à écrire des composants qui ne sont pas seulement fonctionnels, mais agréables à entretenir.

L'anti-modèle « Tout composant »

Parlons de l’erreur classique que nous avons tous commise : le composant tout. Vous l'avez vu : cela commence petit et innocent, peut-être sous la forme d'un simple formulaire ou d'un tableau de bord. Avancez un peu, et maintenant il gère l'état, gère les appels d'API, formate les données et éventuellement prépare votre café du matin.

// Please, no more of this
const UserDashboard = () => {
  const [userData, setUserData] = useState(null);
  const [orders, setOrders] = useState([]);
  const [notifications, setNotifications] = useState([]);
  const [settings, setSettings] = useState({});
  const [isEditing, setIsEditing] = useState(false);
  const [activeTab, setActiveTab] = useState('profile');

  // 15 separate useEffects
  // 10 different event handlers
  // Multiple conditional renders
  // 300+ lines of chaos
};
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cela vous semble familier ?

Comment savoir si vous êtes coupable

Votre composant est peut-être devenu un « composant tout » si :

  • Surcharge d'état : Vous suivez plus de 3 à 4 éléments d'état distincts.
  • Défilement sans fin : Vous passez trop de temps à rechercher des fonctions ou une logique spécifiques.
  • Globation des dépendances : Vos dépendances useEffect ressemblent à votre liste de courses hebdomadaire.
  • Déni de fonctionnalité : Vous n'arrêtez pas de vous dire qu'une seule fonctionnalité de plus ne fera pas de mal.

Le décomposer

La solution ? Au lieu d'un seul composant, divisez les responsabilités en éléments plus petits et ciblés.

// A cleaner, smarter approach
const UserDashboard = () => {
  return (
    <div>
      <UserProfile />
      <OrderHistory />
      <NotificationCenter />
      <UserSettings />
    </div>
  );
};
Copier après la connexion
Copier après la connexion
Copier après la connexion

Principe clé : Logique > Mise en page

Lors de la refactorisation, ne cassez pas les composants en fonction de leur apparence à l'écran. Divisez-les par responsabilité. Posez-vous la question : cette fonctionnalité mérite-t-elle son propre composant ? S'il gère quelque chose de distinct, comme les profils utilisateur ou l'historique des commandes, c'est probablement le cas.

Conseil : Un bon composant fait une chose et la fait bien. Si vous avez du mal à décrire son objectif en une seule phrase, il y a de fortes chances qu'il essaie d'en faire trop.

L'enfer du forage d'hélices

Parlons du jeu pas si amusant de « passer les accessoires ». Si vous avez déjà fait passer le même accessoire à travers plusieurs composants juste pour atteindre un enfant profondément imbriqué, vous avez été coincé dans l'enfer du forage d'accessoires.

// Please, no more of this
const UserDashboard = () => {
  const [userData, setUserData] = useState(null);
  const [orders, setOrders] = useState([]);
  const [notifications, setNotifications] = useState([]);
  const [settings, setSettings] = useState({});
  const [isEditing, setIsEditing] = useState(false);
  const [activeTab, setActiveTab] = useState('profile');

  // 15 separate useEffects
  // 10 different event handlers
  // Multiple conditional renders
  // 300+ lines of chaos
};
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cette approche n’est pas seulement ennuyeuse : elle crée des problèmes à long terme. Imaginez devoir renommer l'accessoire utilisateur. Du coup, vous le mettez à jour à cinq endroits ou plus. Pire encore, vous finissez par lier des composants à des données qu'ils n'utilisent même pas.

Comment résoudre ce problème

Pas besoin de jouer à la patate chaude avec vos accessoires. Voici deux solutions pratiques pour éviter complètement de percer.

1. Utiliser le contexte pour les données partagées

Si une donnée est accessible dans différentes parties de votre application, l'API Context de React peut simplifier les choses.

// A cleaner, smarter approach
const UserDashboard = () => {
  return (
    <div>
      <UserProfile />
      <OrderHistory />
      <NotificationCenter />
      <UserSettings />
    </div>
  );
};
Copier après la connexion
Copier après la connexion
Copier après la connexion

2. Utilisez la composition pour la flexibilité

Au lieu de forcer les accessoires à travers les couches, restructurez les composants afin qu'ils ne transmettent que ce qui est nécessaire.

// This is exhausting
const App = () => {
  const [user, setUser] = useState({});
  return (
    <Layout user={user}>
      <Sidebar user={user}>
        <Navigation user={user}>
          <UserMenu user={user} />
        </Navigation>
      </Sidebar>
    </Layout>
  );
};
Copier après la connexion
Copier après la connexion

Principaux points à retenir

Le contexte fonctionne bien pour les données à l'échelle de l'application, telles que les informations utilisateur, les thèmes ou les paramètres globaux. Cependant, ce n’est pas toujours la meilleure option : n’en abusez pas. Pour un état localisé, demandez-vous si la structure de vos composants peut être ajustée pour éviter complètement le perçage.

L'objectif est de rendre vos composants clairs et maintenables. Éviter le forage d'hélices vous fera gagner du temps, de la frustration et d'innombrables maux de tête sur la route.

Pièges d’optimisation prématurée

Vous avez probablement entendu cette célèbre citation selon laquelle l'optimisation prématurée est la racine de tous les maux. Eh bien, bienvenue dans le mal au niveau des composants. Je parle de ces moments où nous essayons de tout rendre réutilisable avant même de savoir si nous en aurons besoin deux fois.

Voici à quoi cela ressemble habituellement :

const UserContext = createContext();

const App = () => {
  const [user, setUser] = useState({});
  return (
    <UserContext.Provider value={user}>
      <Layout>
        <Sidebar>
          <Navigation />
        </Sidebar>
      </Layout>
    </UserContext.Provider>
  );
};

// Use it only where needed
const UserMenu = () => {
  const user = useContext(UserContext);
  return <div>{user.name}</div>;
};
Copier après la connexion

Laissez vos composants évoluer naturellement. Construisez pour ce dont vous savez avoir besoin aujourd’hui. Si de nouvelles exigences surviennent, ajoutez des fonctionnalités lorsque vous pouvez les justifier clairement. Une optimisation prématurée fait perdre du temps, ajoute de la complexité et est rarement payante.

Rappelez-vous : Le principe YAGNI (You Aren’t Gonna Need It) s’applique également aux composants. Les meilleures abstractions surviennent lorsque vous avez réellement rencontré les problèmes qu’elles résolvent. La sur-ingénierie peut sembler proactive, mais la simplicité l'emporte à chaque fois.

Mauvaise gestion des effets secondaires

Voici un exemple classique de mauvaise gestion des effets. Vous semblez familier ?

// Focused components for better clarity
const Navigation = ({ children }) => {
  return <nav>{children}</nav>;
};

// Pass data only where required
const App = () => {
  const user = useUser();
  return (
    <Layout>
      <Navigation>
        <UserMenu user={user} />
      </Navigation>
    </Layout>
  );
};
Copier après la connexion

Erreurs et correctifs courants

1) Récupération de données désordonnée

Une mauvaise gestion des données crée plus de bugs qu’elle n’en résout. Voici une approche plus propre :

// Behold, the over-engineered button
const Button = ({ 
  children,
  variant = 'primary',
  size = 'medium',
  isFullWidth = false,
  isDisabled = false,
  isLoading = false,
  leftIcon,
  rightIcon,
  onClick,
  customClassName,
  style,
  loadingText = 'Loading...',
  tooltipText,
  animationType,
  // ... 10 more props
}) => {
  // 50 lines of prop processing logic
  return (
    <button 
      className={generateComplexClassNames()}
     >



<h3>
  
  
  Why This Hurts
</h3>

<ul>
<li>Your “simple” button now requires an instruction manual.</li>
<li>Most of those 15+ props will never be used.</li>
<li>Making updates becomes risky because you have to account for endless combinations.</li>
<li>Writing tests becomes painful, with a hundred possible scenarios to consider.</li>
</ul>

<h3>
  
  
  Better Approach:
</h3>

<p>Instead of building for every imaginable scenario, start small and let your components grow as needed.<br>
</p>

<pre class="brush:php;toolbar:false">// Start simple
const Button = ({ children, onClick, variant = 'primary' }) => {
  return (
    <button 
      className={`btn btn-${variant}`}
      onClick={onClick}
    >
      {children}
    </button>
  );
}

// Create specific buttons when you actually need them
const LoadingButton = ({ isLoading, children, ...props }) => {
  return (
    <Button {...props}>
      {isLoading ? 'Loading...' : children}
    </Button>
  );
}
Copier après la connexion

2) Oublier le nettoyage

Nettoyez toujours après vous :

const UserProfile = ({ userId }) => {  
  const [user, setUser] = useState(null);  
  const [posts, setPosts] = useState([]);  

  // Dependency array woes
  useEffect(() => {  
    fetchUserData(userId);  
    fetchUserPosts(userId);  
    // No cleanup? Yikes.
  }, []); // eslint-disable-line react-hooks/exhaustive-deps  

  // Multiple effects, all tangled
  useEffect(() => {  
    const subscription = subscribeToUserStatus(userId);  
  }, [userId]);  

  // Cleanup? What cleanup?
  useEffect(() => {  
    const interval = setInterval(checkNotifications, 5000);  
  }, []);  
};
Copier après la connexion

3) Ignorer les conditions de course

Évitez les demandes qui se chevauchent avec cette technique :

// Improved version
const UserProfile = ({ userId }) => {  
  const { data: user, isLoading } = useQuery(  
    ['user', userId],  
    () => fetchUserData(userId)  
  );  

  // Keep concerns separate
  const { data: posts } = useQuery(  
    ['posts', userId],  
    () => fetchUserPosts(userId),  
    { enabled: !!user }  
  );  
};
Copier après la connexion

Conseils rapides

  • Réfléchissez avant d'utiliser useEffect : parfois, vous n'en aurez peut-être pas besoin du tout.
  • Gardez-vous concentré : un effet doit gérer une responsabilité.
  • Toujours nettoyer : les abonnements, les intervalles et les auditeurs d'événements nécessitent une attention particulière.
  • Utilisez les bons outils : les bibliothèques comme React Query simplifient la récupération et la mise en cache des données.
  • Ne trichez pas avec eslint-disable : corrigez les problèmes de dépendance au lieu de les masquer.

Angles morts des performances

Parlons de ces problèmes de performances sournois. Ils sont du genre à passer inaperçus parce que tout semble bien, jusqu’à ce que ce ne soit plus le cas. Découvrons ces coupables silencieux et voyons comment y remédier.

Le problème

Voici un composant présentant quelques pièges subtils en termes de performances :

// Please, no more of this
const UserDashboard = () => {
  const [userData, setUserData] = useState(null);
  const [orders, setOrders] = useState([]);
  const [notifications, setNotifications] = useState([]);
  const [settings, setSettings] = useState({});
  const [isEditing, setIsEditing] = useState(false);
  const [activeTab, setActiveTab] = useState('profile');

  // 15 separate useEffects
  // 10 different event handlers
  // Multiple conditional renders
  // 300+ lines of chaos
};
Copier après la connexion
Copier après la connexion
Copier après la connexion

Pouvez-vous repérer les problèmes ? Décomposons-les.

Corrections

1) Mémorisez les calculs coûteux

Au lieu de tout recalculer à chaque rendu, utilisez useMemo pour mettre en cache les résultats :

// A cleaner, smarter approach
const UserDashboard = () => {
  return (
    <div>
      <UserProfile />
      <OrderHistory />
      <NotificationCenter />
      <UserSettings />
    </div>
  );
};
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cela évite de recalculer les données et de recréer les gestionnaires d'événements à chaque rendu. Cela évite également les nouveaux rendus inutiles des composants enfants avec mémo.

2) Mises à jour efficaces de l'état

Une mauvaise gestion de l’État peut également nuire aux performances. Voici une meilleure façon de gérer les mises à jour telles que les résultats de recherche :

// This is exhausting
const App = () => {
  const [user, setUser] = useState({});
  return (
    <Layout user={user}>
      <Sidebar user={user}>
        <Navigation user={user}>
          <UserMenu user={user} />
        </Navigation>
      </Sidebar>
    </Layout>
  );
};
Copier après la connexion
Copier après la connexion

L'anti-rebond garantit que nous ne récupérons pas de données à chaque frappe, ce qui réduit les appels d'API et les rendus inutiles.

Conseils rapides sur les performances

  • N'abusez pas de la mémorisation : optimisez uniquement lorsque cela en vaut la peine.
  • Évitez les fonctions en ligne : les références stables améliorent les performances.
  • Gardez les accessoires prévisibles : les accessoires peu profonds et stables aident les composants à rester efficaces.
  • Séparez les grandes listes : des outils tels que React-window peuvent gérer de gros ensembles de données avec élégance.
  • Rapprochez l’état : gérez l’état uniquement là où il est réellement nécessaire.
  • Profil avec DevTools : mesurez toujours avant d'optimiser.

Conclusion

Construire des composants n’est pas compliqué, mais soyons réalistes : il est facile de prendre de mauvaises habitudes. J'ai commis chacune de ces erreurs (et je le fais parfois encore). Ce n'est pas grave. Ce qui compte, c'est de les détecter tôt, de les corriger et d'éviter une base de code grossière.

Liste de contrôle rapide pour de meilleurs composants

✅ Responsabilité unique : Si vous ne pouvez pas résumer le travail de votre composant en une phrase, il est temps de le décomposer.

✅ Gestion des accessoires : passer les accessoires de couches en couches ? Envisagez plutôt d'utiliser le contexte ou de tirer parti de la composition.

✅ État et effets : gardez les effets concentrés, nettoyez-les correctement et laissez les outils modernes gérer la récupération de données complexes.

✅ Performance : n'optimisez pas pour le plaisir : mesurez d'abord. Utilisez intelligemment des outils tels que memo, useMemo et useCallback en cas de besoin.

✅ Commencez simplement : résolvez les problèmes que vous rencontrez maintenant, pas ceux que vous pourriez avoir un jour.

Les meilleurs composants ne sont ni tape-à-l’œil ni trop intelligents : ce sont ceux que votre équipe peut lire et maintenir sans gémir six mois plus tard.

Rappelez-vous : ce ne sont pas des règles strictes, juste des lignes directrices. Vous les casserez parfois, et c’est parfaitement bien. L’objectif n’est pas la perfection : il s’agit de créer des éléments qui ne vous amèneront pas à remettre en question vos choix de carrière lorsque vous les revisiterez plus tard.

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!

source:dev.to
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