Просунуті патерни React та найкращі практики

React — це потужна бібліотека для створення інтерфейсів користувача, але разом із зростанням вашого застосунку зростає і його складність. Щоб керувати цією складністю, використовуються просунуті патерни React. Ці патерни допомагають створювати багаторазові, підтримувані та масштабовані компоненти. У цьому блозі ми розглянемо три популярні просунуті патерни React: компоненти вищого порядку (Higher-Order Components, HOCs), Render Props і компонентні патерни Compound Components. Розуміння цих патернів допоможе вам вивести свої навички React на новий рівень і створювати кращі та ефективніші застосунки.

pic

1. Компоненти вищого порядку (Higher-Order Components, HOCs)

Компонент вищого порядку (Higher-Order Component, HOC) — це функція, яка приймає компонент і повертає новий компонент. Цей патерн використовується для повторного використання логіки компонентів, наприклад, для обробки аутентифікації, перевірки дозволів або отримання даних.
HOC дозволяють винести повторювану логіку в одну функцію та застосовувати її до кількох компонентів.

Приклад: HOC для отримання даних

import React, { useEffect, useState } from 'react';  

// HOC для отримання даних  
function withDataFetching(WrappedComponent, url) {  
 return function WithDataFetchingComponent(props) {  
   const [data, setData] = useState([]);  
   const [loading, setLoading] = useState(true);  

   useEffect(() => {  
     fetch(url)  
       .then(response => response.json())  
       .then(data => {  
         setData(data);  
         setLoading(false);  
       });  
   }, [url]);  

   return <WrappedComponent {...props} data={data} loading={loading} />;  
 };  
}  

// Компонент, що використовує HOC  
function MyComponent({ data, loading }) {  
 if (loading) {  
   return <div>Завантаження...</div>;  
 }  

 return (  
   <ul>  
     {data.map(item => (  
       <li key={item.id}>{item.name}</li>  
     ))}  
   </ul>  
 );  
}  

export default withDataFetching(MyComponent, 'https://api.example.com/data');

У цьому прикладі HOC withDataFetching відповідає за отримання даних і передавання їх до компонента WrappedComponent.
Ви можете повторно використовувати цей HOC із будь-яким компонентом, який потребує логіки отримання даних, роблячи ваш код більш чистим і багаторазовим.

Коли використовувати HOC

  • Для повторного використання спільної логіки між кількома компонентами.
  • Для абстрагування задач, таких як аутентифікація, перевірка дозволів або отримання даних.
  • Щоб компоненти залишалися зосередженими на своїй основній меті (рендеринг UI), передаючи логіку HOC.

Render Props

Патерн Render Props дозволяє ділитися логікою між компонентами, передаючи функцію як пропс (Prop).
Ця функція називається «render prop» і дозволяє батьківському компоненту контролювати, як рендериться дочірній компонент.

Приклад: Render Props для відстеження позиції миші

import React, { useState } from 'react';  

// Компонент, що використовує render props  
function MouseTracker({ render }) {  
 const [position, setPosition] = useState({ x: 0, y: 0 });  

 const handleMouseMove = (event) => {  
   setPosition({ x: event.clientX, y: event.clientY });  
 };  

 return <div onMouseMove={handleMouseMove}>{render(position)}</div>;  
}  

// Компонент, що використовує MouseTracker із render prop  
function App() {  
 return (  
   <MouseTracker  
     render={(position) => (  
       <p>Позиція миші: {position.x}, {position.y}</p>  
     )}  
   />  
 );  
}  

export default App;  

У цьому прикладі компонент MouseTracker не визначає, як має відображатися позиція миші.
Замість цього він використовує пропс render, щоб делегувати логіку рендерингу батьківському компоненту, роблячи патерн гнучким і багаторазовим.

Коли використовувати Render Props

  • Для спільного використання логіки, дозволяючи гнучкість у рендерингу.
  • Для уникнення глибокої передачі пропсів (Prop Drilling), інкапсулюючи логіку в багаторазовий компонент.
  • Для динамічного рендерингу на основі спільної логіки, наприклад, анімацій або відстеження подій.

Compound Components

Compound Components — це патерн проєктування, який дозволяє створювати набір компонентів, що працюють разом і ділять між собою внутрішній стан.
Цей патерн часто використовується для створення компонентів, таких як вкладки (Tabs), акордеони (Accordions) або випадаючі списки (Dropdowns), де кілька дочірніх компонентів залежать від спільного стану.

Приклад: Compound Components для кнопки-перемикача

import React, { useState } from 'react';  

// Батьківський компонент  
function Toggle({ children }) {  
 const [on, setOn] = useState(false);  
 const toggle = () => setOn(!on);  
 return React.Children.map(children, (child) =>  
   React.cloneElement(child, { on, toggle })  
 );  
}  

// Дочірні компоненти  
function ToggleButton({ on, toggle }) {  
 return <button onClick={toggle}>{on ? 'Увімкнено' : 'Вимкнено'}</button>;  
}  

function ToggleMessage({ on }) {  
 return <p>{on ? 'Кнопка увімкнена' : 'Кнопка вимкнена'}</p>;  
}  

// Використання компонентів разом  
function App() {  
 return (  
   <Toggle>  
     <ToggleButton />  
     <ToggleMessage />  
   </Toggle>  
 );  
}  

export default App;

У цьому прикладі компонент Toggle керує станом, а компоненти ToggleButton та ToggleMessage рендерять різні елементи інтерфейсу залежно від цього стану.
Батьківський компонент передає стан і поведінку кожному дочірньому компоненту, дозволяючи їм взаємодіяти та ділитися логікою без глибокої передачі пропсів (Prop Drilling).

Коли використовувати Compound Components

  • Для створення набору компонентів, які працюють разом як єдиний модуль.
  • Для побудови гнучких елементів інтерфейсу, таких як вкладки (Tabs), акордеони (Accordions) або випадаючі списки (Dropdowns).
  • Для спрощення управління станом пов’язаних компонентів.

Найкращі практики для просунутих патернів React

  • Тримайте компоненти простими: Не зловживайте просунутими патернами. Починайте з простого підходу та впроваджуйте ці патерни лише тоді, коли вони вирішують конкретну проблему, наприклад, багаторазовість або масштабованість.
  • Уникайте надмірної абстракції: Хоча абстракція корисна, її надлишок може зробити ваш код важчим для розуміння та підтримки. Переконайтеся, що кожен патерн додає цінність.
  • Обирайте правильний патерн для завдання: Не всі патерни підходять для кожного сценарію.
    Наприклад, HOCs і Render Props можуть вирішувати одну й ту саму проблему, але один із них може бути більш доречним залежно від вашого випадку використання.

  • Тестуйте багаторазовість: Переконайтеся, що ваші HOCs, Render Props або Compound Components є багаторазовими та зручними для підтримки. Спробуйте використовувати їх у різних контекстах, щоб перевірити їхню гнучкість.

Просунуті патерни React, такі як компоненти вищого порядку (Higher-Order Components), Render Props і Compound Components, є потужними інструментами для управління складністю ваших застосунків. Абстрагуючи спільну логіку, ділячись поведінкою та організовуючи пов’язані компоненти, ви можете зробити ваші React-застосунки більш ефективними, гнучкими та зручними для підтримки. Незалежно від того, чи створюєте ви багаторазові компоненти, чи керуєте складною логікою стану, ці патерни допоможуть вам писати чистіший і масштабованіший код.

Готові зануритися глибше в розробку на React? Спробуйте впровадити ці патерни у свої проєкти й подивіться, як вони покращать структуру та підтримуваність вашого коду.
Не забудьте поділитися своїм досвідом у коментарях і стежте за цим блогом для отримання нових уроків з React! Успішного кодування!

Перекладено з: Advanced React Patterns and Best Practices

Leave a Reply

Your email address will not be published. Required fields are marked *