5 лучших практик для React разработчиков
2 года назад·6 мин. на чтение
В этой статье мы рассмотрим пять наиболее распространенных лучших практик для React разработчиков. React был разработан для того, чтобы его можно было настроить именно так, как вам нужно - он не имеет жестких ограничений. Поэтому, если эти пять сценариев лучших практик вам не подходят, вы можете найти свой собственный подход.
Существует множество способов структурировать код так, чтобы он был читабельным, и у каждого свой подход к этому. Возникает вопрос, есть ли лучший способ сделать это?
Мы поговорим о лучших практиках:
- Организация каталога
- Компоненты и разделение ответственности
- Работа с состояниями
- Абстракция
- Соглашения об именовании
1. Организация каталогов
В документации React упоминается, что в целом существует два основных способа организации вашего приложения React: Группировка по функциям или маршрутам и Группировка по типу файлов. Главное здесь - не перемудрить. Если вы начинаете с небольшого приложения, вы можете органично организовать свой код по ходу работы так, как вам удобно. Помните, что React не имеет собственной жесткой структуры, поэтому на 100% зависит от вас, как все будет структурировано. Если у вас есть логическое объяснение тому, как организованы файлы, то все хорошо. Однако, поскольку в документации React упоминаются эти две стратегии организации, давайте рассмотрим каждую из них, чтобы понять, как они структурированы. Допустим, у нас есть приложение для электронной коммерции, в котором есть пользователь, список товаров, подробная страница товара, корзина и процесс оформления заказа.Группировка по функциям
Корневой каталог здесь - это каталогsrc
, который является одним из двух базовых каталогов в вашем приложении React (второй - папка public
). В каталоге src
у нас будут основные файлы App.js
и index.js
в корне папки. Затем у нас будут вложенные каталоги для каждой из функций вашего приложения.
Ваш подход к структуре может варьироваться в зависимости от того, как все организовано: в проекте может быть больше каталогов, меньше каталогов или даже более глубокая вложенность на компоненты, стилизацию и тестирование.
src/ App.js App.css App.test.js index.js global/ <= общие для всего приложения сущности AppContext.js ThemeContext.js UserContext.js Button.js cards/ index.js Cards.css Cards.js Card.css Card.js Card.test.js detailed-product/ DetailedProduct.css DetailedProduct.js DetailedProduct.test.js checkout/ ReviewOrder.css ReviewOrder.js ReviewOrder.test.js ShoppingCart.css ShoppingCart.js ShoppingCart.test.js user/ index.js User.css User.js User.test.js
Группировка по типу файлов
Корневой каталог по-прежнему является каталогомsrc
. Все, что будет отображаться на экране клиента, по-прежнему находится в этой папке. Как и раньше, мы будем хранить файлы App.js
и index.js
в корне этого каталога, а затем каталоги, представляющие составные части приложения: компоненты, контекст, CSS, хуки и тесты.
Как и прежде, способ настройки проекта зависит от вашего приложения и от того, как вы хотите его реализовать. Основная структура здесь зависит от типа файла и не более того. В конечном итоге структура вашего файла должна быть сделана так, чтобы в ней было легко ориентироваться. Как вы это сделаете, зависит только от вас. О других вариантах структурирования React приложения читайте в:src/ App.js index.js components/ App.css Card.js Cards.js ConfirmationPage.js DetailedProduct.js Footer.js Navbar.js ReviewOrder.js Settings.js ShoppingCart.js User.js context/ AppContext.js ThemeContext.js UserContext.js css/ Card.css Cards.css ConfirmationPage.css DetailedProduct.css Footer.css Navbar.css ReviewOrder.css Settings.css ShoppingCart.css User.css hooks/ useAuth.js useAxios.js tests/ App.test.js Card.test.js Cards.test.js ConfirmationPage.test.js DetailedProduct.test.js Footer.test.js Navbar.test.js ReviewOrder.test.js Settings.test.js ShoppingCart.test.js User.test.js
2. Компоненты и разделение ответственности
До появления React Hooks было довольно легко определить, что считается компонентом класса с состоянием, а что - презентационным функциональным компонентом. Некоторые разработчики также называли их "умными" компонентами и "глупыми" компонентами. Разумеется, умные компоненты - это те, которые несут состояние и обрабатывают логику, а глупые компоненты - это те, которые просто принимают передаваемые им пропсы. После появления React Hooks и обновления Context API почти все можно считать функциональным компонентом, что приводит к разговору о том, когда следует разделять компоненты, содержащие локальное состояние, и компоненты, которые его не содержат, и как это делать. В конечном счете, это зависит от вас и/или вашей команды, как построить ваш паттерн проектирования, но лучшая практика показывает, что логика и компоненты с локальным состоянием должны быть отделены от статических компонентов. Подробнее о разделении ответственности читайте в статье Разделение ответственности в React. Как использовать контейнерные и презентационные компоненты..3. Работа с состоянием и пропсами
Поток данных в React-приложении очень важен. Есть два способа работы с данными: использование состояния или передача состояния в виде пропсов. Давайте рассмотрим лучшие практики.Состояние
При работе с состоянием, будь то глобально в контекстном API или локально, его нельзя изменять напрямую, переназначая свойство state с новым значением:Вместо этого при работе с состоянием в классовых компонентах используйте методaddOne = () => { // Так обновлять состояние нельзя this.state.counter += 1; }
this.setState()
для обновления состояния.
При использовании React Hooks вы будете использовать любое название своегоimport React from "react"; import "./styles.css"; class Counter extends React.Component{ constructor(props) { super(props); this.state = { counter: 0 } } addOne = () => { this.setState({counter: this.state.counter + 1}) } subtractOne = () => { this.setState({counter: this.state.counter - 1}); } reset = () => { this.setState({ counter: 0 }); } render() { return ( <div className="App"> <h1>Simple React Counter</h1> <h2>{this.state.counter}</h2> <button onClick={this.addOne}> + </button> <button onClick={this.reset}> Reset </button> <button onClick={this.subtractOne}> - </button> </div> ); } } export default Counter;
set
метода:
import React, { useState } from "react"; import "./styles.css"; export default function App() { const [ counter, setCounter ] = useState(0); const addOne = () => { setCounter(counter + 1) } const subtractOne = () => { setCounter(counter - 1); } const reset = () => { setCounter(0); } return ( <div className="App"> <h1>Simple React Counter</h1> <h2>{counter}</h2> <button onClick={subtractOne}> - </button> <button onClick={reset}> Reset </button> <button onClick={addOne}> + </button> </div> ); }
Пропсы
При работе с пропсами и передаче состояния другим компонентам для использования, может наступить момент, когда вам потребуется передать пропсы пяти дочерним компонентам. Такой метод передачи пропсов от родителя к ребенку на протяжении нескольких поколений называется prop drilling, и его следует избегать. Хотя код, безусловно, будет работать, если вы будете передавать проп на много уровней вниз, он подвержен ошибкам, и поток данных может быть трудно отслеживать. Вам следует создать какой-либо паттерн проектирования для глобального управления состоянием с помощью Redux или Context API (Context API в настоящее время является более простым и предпочтительным способом). Подробнее о вариантах передачи данных между реакт компонентами читайте в статье Как передавать данные между компонентами в ReactJS4. Абстракция
React процветает благодаря возможности повторного использования. Когда мы говорим о лучших практиках React, часто встречается термин абстракция. Абстракция означает, что есть части большого компонента или приложения, которые могут быть изъяты, превращены в собственный функциональный компонент, а затем импортированы в более крупный компонент. Если сделать компонент как можно проще, часто так, чтобы он служил только одной цели, это увеличивает шансы на многократное использование кода. В простом приложении счетчика, созданном выше, есть возможность абстрагировать некоторые элементы от компонентаApp
. Кнопки могут быть абстрагированы в собственный компонент, где мы передаем метод и метку кнопки в качестве пропсов.
Заголовок и название приложения также могут быть размещены в собственных компонентах. После того как мы абстрагировали все элементы, компонент App
может выглядеть примерно так:
Основная цель абстракции - сделать дочерние компоненты как можно более общими, чтобы их можно было использовать повторно в любом нужном вам виде. App-компонент должен содержать только ту информацию, которая специфична для приложения, и выводить или возвращать только более мелкие компоненты.import React, { useState } from "react"; import { Button } from "./Button"; import { Display } from "./Display"; import { Header } from "./Header"; import "./styles.css"; export default function App() { const addOne = () => { setCounter(counter + 1) } const subtractOne = () => { setCounter(counter - 1); } const reset = () => { setCounter(0); } const initialState = [ {operation: subtractOne, buttonLabel:"-"}, {operation: reset, buttonLabel: "reset"}, {operation: addOne, buttonLabel: "+"} ] const [ counter, setCounter ] = useState(0); const [ buttonContents, ] = useState(initialState) return ( <div className="App"> <Header header="Simple React Counter"/> <Display counter={counter}/> {buttonContents.map(button => { return ( <Button key={button.operation + button.buttonLabel} operation={button.operation} buttonLabel={button.buttonLabel} /> ) })} </div> ); }
5. Соглашения об именовании
В React есть три основных соглашения об именовании, которые следует рассматривать как лучшие практики.- Компоненты должны быть написаны в PascalCase - а также и названы по их основной функциональности, а не по специфике приложения (на случай, если вы измените ее позже).
- Элементы, которым нужны ключи, должны быть уникальными, неслучайными идентификаторами (например, отдельные карты или записи в карточной колоде или списке). Лучшая практика - не использовать для ключей только индексы. Допустимо назначение ключа, состоящего из конкатенации двух различных свойств объекта.
key={button.operation + button.buttonLabel}
- Методы должны быть в camelCase и называться по их назначению, а не быть специфичными для приложения. По тем же причинам, что и компоненты в PascalCase, методы должны быть названы по их назначению, а не по их особенности в приложении.
Итоги
В этой статье мы рассмотрели пять лучших практик, которые следует применять при разработке на React. Во многих случаях речь идет о том, что подходит вам и вашей команде, а не о том, что конкретно считается "лучшей практикой". Именно разработчики, которые впоследствии будут редактировать и читать ваш код, должны будут уметь расшифровывать и улучшать ваш проект.Архитектура веб-приложений
год назад·1 мин. на чтение
Что такое архитектура веб-приложения и как спроектировать приложение
Существует много вариантов архитектур для построения веб-приложений.
В понятие архитектуры можно включить множество вопросов. Буквально все вопросы, которые появляются перед тем как начинать делать проект, можно отнести к архитектуре. От ответов на эти вопросы будет зависеть архитектура веб приложения.
При построении архитектуры нужно исходить из потребностей и требований. Если требования не ясны, то следует исключить все пробелы.
Если у приложения есть публичная часть, которая должна индексироваться поисковиками, то следует посмотреть в сторону рендеринга на стороне сервера и соответствующие фреймворки. Это блоги, новостные сайты, интернет магазины, маркетплейсы и т.д.
Если веб-приложение представляет собой приватное приложение, то отличным вариантом может стать решение на основе рендеринга на стороне клиента (CSR). Это решения, основанные на SPA (Single Page Application), написанные с помощью фреймворков React, Angular, Vue, Svelte или PWA (Progressive Web Apps). Примерами таких приложений могут быть приложения для автосалонов, через которые зарегистрированный пользователь может записаться на техобслуживание.
С ростом проекта нужно правильно организовать не только проект, но и работу команд. Стоит рассмотреть разделение монолита на микросервисы на бекенде, и на микрофронтенды на фронтенде.
В архитектуру приложения также входит устройство бэкэнда и баз данных, наличие балансировщиков нагрузки, CDN, горизонтальное и вертикальное масштабирование и т.д.
Также тема архитектуры веб-приложений популярна на собеседовании. Обычно блок вопросов по архитектуре выносят в отдельное интервью по System Design. Также рекомендую ознакомиться с обзором на книгу, которая будет полезна при проектировании высоконагруженных систем.
Смотреть на Rutube