Полезные библиотеки для React-приложений в 2025 году: на что обратить внимание

от автора

Привет, Хабрчане! Это Леша Жиряков, техлид backend-команды витрины KION. В прошлый раз я писал о секретах популярности Python, а сегодня будет пост о разработке на React. Расскажу, какие библиотеки стоит добавить в свой набор в 2025 году, приведу плюсы и минусы каждой, данные с GitHub и примеры использования. Начнем!

Tremor

Tremor — UI-библиотека для создания дашбордов и аналитических интерфейсов в React. В отличие от инструментов, заточенных исключительно на визуализации данных, Tremor предлагает готовые UI-компоненты: карточки, таблицы, кнопки, графики, фильтры и так далее. Библиотека построена на Tailwind CSS (об этом в блоге писал коллега), так что она удобна для кастомизации.

Главная идея Tremor — ускорить разработку дашбордов, предоставив хорошо стилизованные и адаптивные компоненты. Например, можно за несколько строк кода создать карточку с ключевой метрикой или быстро интегрировать диаграмму из Recharts, Nivo или ECharts. Поддерживается темная и светлая темы, предусмотрена адаптация к разным экранам.

Плюсы:

  • готовые UI-компоненты, сокращающие время разработки;

  • легкая интеграция с Recharts, Nivo и ECharts;

  • гибкость благодаря Tailwind CSS.

Минусы:

  • ограниченная кастомизация в сравнении с чистыми UI-фреймворками;

  • не предназначен для сложных и нестандартных интерфейсов.

GitHub:

  • количество звезд: 2,1 тыс.;

  • открытых Issues: 11;

  • год релиза: 2024;

  • Merge Requests (MRs): разработчики проекта и сообщество.

Отличный выбор, если нужно быстро развернуть дашборд с минимальными усилиями, но для более детальной настройки могут потребоваться другие UI-библиотеки.

Еще о сильных сторонах

Tremor содержит в себе множество готовых компонентов: графики (Area Chart, Bar Chart, Donut Chart, Progress Bar), элементы для ввода (Calendar, Checkbox, Date Picker, Radio Card Group) и другие UI-элементы (Badge, Button, Dialog, Table).

Например, мы хотим добавить кнопку (Button). В документации Tremor весь код уже написан: Ctrl + C, Ctrl + V — и вперед!

Устанавливаем зависимости:

npm install @radix-ui/react-slot tailwind-variants @remixicon/react

Добавляем код в директорию проекта, где хранятся компоненты. Важно не забыть обновить импорты:

// Tremor Button [v0.2.0]  import React from "react" import { Slot } from "@radix-ui/react-slot" import { RiLoader2Fill } from "@remixicon/react" import { tv, type VariantProps } from "tailwind-variants"   import { cx, focusRing } from "@/lib/utils"   const buttonVariants = tv({  base: [    // base    "relative inline-flex items-center justify-center whitespace-nowrap rounded-md border px-3 py-2 text-center text-sm font-medium shadow-sm transition-all duration-100 ease-in-out",    // disabled    "disabled:pointer-events-none disabled:shadow-none",    // focus    focusRing,  ],  variants: {    variant: {      primary: [        // border        "border-transparent",        // text color        "text-white dark:text-white",        // background color        "bg-blue-500 dark:bg-blue-500",        // hover color        "hover:bg-blue-600 dark:hover:bg-blue-600",        // disabled        "disabled:bg-blue-300 disabled:text-white",        "disabled:dark:bg-blue-800 disabled:dark:text-blue-400",      ],      secondary: [        // border        "border-gray-300 dark:border-gray-800",        // text color        "text-gray-900 dark:text-gray-50",        // background color        "bg-white dark:bg-gray-950",        //hover color        "hover:bg-gray-50 dark:hover:bg-gray-900/60",        // disabled        "disabled:text-gray-400",        "disabled:dark:text-gray-600",      ],      light: [        // base        "shadow-none",        // border        "border-transparent",        // text color        "text-gray-900 dark:text-gray-50",        // background color        "bg-gray-200 dark:bg-gray-900",        // hover color        "hover:bg-gray-300/70 dark:hover:bg-gray-800/80",        // disabled        "disabled:bg-gray-100 disabled:text-gray-400",        "disabled:dark:bg-gray-800 disabled:dark:text-gray-600",      ],      ghost: [        // base        "shadow-none",        // border        "border-transparent",        // text color        "text-gray-900 dark:text-gray-50",        // hover color        "bg-transparent hover:bg-gray-100 dark:hover:bg-gray-800/80",        // disabled        "disabled:text-gray-400",        "disabled:dark:text-gray-600",      ],      destructive: [        // text color        "text-white",        // border        "border-transparent",        // background color        "bg-red-600 dark:bg-red-700",        // hover color        "hover:bg-red-700 dark:hover:bg-red-600",        // disabled        "disabled:bg-red-300 disabled:text-white",        "disabled:dark:bg-red-950 disabled:dark:text-red-400",      ],    },  },  defaultVariants: {    variant: "primary",  }, })   interface ButtonProps  extends React.ComponentPropsWithoutRef<"button">,    VariantProps<typeof buttonVariants> {  asChild?: boolean  isLoading?: boolean  loadingText?: string }   const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(  (    {      asChild,      isLoading = false,      loadingText,      className,      disabled,      variant,      children,      ...props    }: ButtonProps,    forwardedRef,  ) => {    const Component = asChild ? Slot : "button"    return (      <Component        ref={forwardedRef}        className={cx(buttonVariants({ variant }), className)}        disabled={disabled || isLoading}        tremor-id="tremor-raw"        {...props}      >        {isLoading ? (          <span className="pointer-events-none flex shrink-0 items-center justify-center gap-1.5">            <RiLoader2Fill              className="size-4 shrink-0 animate-spin"              aria-hidden="true"            />            <span className="sr-only">              {loadingText ? loadingText : "Loading"}            </span>            {loadingText ? loadingText : children}          </span>        ) : (          children        )}      </Component>    )  }, )   Button.displayName = "Button"   export { Button, buttonVariants, type ButtonProps }

Используем такой блок кода:

import { Button } from '@/components/Button';  export const ButtonHero = () => (  <div className="flex justify-center">    <Button asChild>      <a href="#hello">Hello, Habr!</a>    </Button>  </div> );

Готово! Получаем следующую кнопку:

Planby

Специализированный React-компонент для отображения таймлайнов, расписаний и диаграмм Ганта. В отличие от универсальных библиотек визуализации вроде Recharts или Nivo, Planby заточен именно под временные шкалы и позволяет эффективно рендерить большие объемы данных.

Библиотека использует виртуализацию, поэтому она хороша даже при работе с тысячами событий. Поддерживает горизонтальную прокрутку, масштабирование временной шкалы и кастомизацию элементов. Planby удобен для интеграции в дашборды, системы управления проектами и любые приложения, где нужно визуализировать временные интервалы.

Плюсы:

  • гибкость в кастомизации отображения событий;

  • поддержка горизонтальной прокрутки и масштабирования.

Минусы:

  • подходит только для таймлайнов и расписаний;

  • ограниченная документация и сравнительно небольшое сообщество;

  • может потребовать дополнительных стилей для полной адаптации под дизайн системы.

GitHub:

  • Количество звезд: 1,5 тыс.

  • Открытых Issues: 6.

  • Версия: 1.1.7.

  • Год релиза: 2022.

  • Merge Requests (MRs): главный разработчик и сообщество. Сейчас открытых MRs и нет, последние изменения вносились в проект два года назад.

Если нужно отобразить расписание, временную диаграмму или диаграмму Ганта в React, Planby — одно из лучших решений.

Еще о сильных сторонах

Есть три способа, как можно использовать Planby.

Стандартный шаблон:

import { useEpg, Epg, Layout } from 'planby';  const channels = React.useMemo(   () => [     {       logo: 'https://via.placeholder.com',       uuid: '10339a4b-7c48-40ab-abad-f3bcaf95d9fa',       ...     },   ],   [] );  const epg = React.useMemo(   () => [     {       channelUuid: '30f5ff1c-1346-480a-8047-a999dd908c1e',       description:         'Ut anim nisi consequat minim deserunt...',       id: 'b67ccaa3-3dd2-4121-8256-33dbddc7f0e6',       image: 'https://via.placeholder.com',       since: "2022-02-02T23:50:00",       till: "2022-02-02T00:55:00",       title: 'Title',       ...     },   ],   [] );  const {   getEpgProps,   getLayoutProps,   onScrollToNow,   onScrollLeft,   onScrollRight, } = useEpg({   epg,   channels,   startDate: '2022/02/02', // or 2022-02-02T00:00:00 });  return (   <div>     <div style={{ height: '600px', width: '1200px' }}>       <Epg {...getEpgProps()}>         <Layout           {...getLayoutProps()}         />       </Epg>     </div>   </div> );

Настройка ширины и высоты:

const {   getEpgProps,   getLayoutProps,   ... } = useEpg({   epg,   channels,  startDate: '2022/02/02', // or 2022-02-02T00:00:00   width: 1200,   height: 600 });  return (   <div>      <Epg {...getEpgProps()}>         <Layout           {...getLayoutProps()}         />       </Epg>   </div>

Настройка временного диапазона:

const {   getEpgProps,   getLayoutProps,   ... } = useEpg({   epg,   channels,   startDate: '2022-02-02T10:00:00',   endDate: '2022-02-02T20:00:00',   width: 1200,   height: 600 });  return (   <div>      <Epg {...getEpgProps()}>         <Layout           {...getLayoutProps()}         />       </Epg>   </div>

Так выглядит горизонтальный скролл:

React DnD

React DnD — библиотека для реализации Drag & Drop в React на основе HTML5 API. Позволяет настраивать перетаскивание элементов через React-компоненты, упрощая код. Еще одно достоинство — гибкость и высокая производительность.

В отличие от более простых решений, таких как react-beautiful-dnd, библиотека предлагает гибкую систему декораторов (useDrag и useDrop) и контекстов, так что она универсальнее. React DnD поддерживает сложные сценарии перетаскивания, включая вложенные иерархии, перенос элементов между разными списками и обработку состояния в Redux.

Плюсы:

  • легковесная, интегрируется с React;

  • гибкость — можно настраивать практически любые сценарии;

  • хорошая поддержка и документация.

Минусы:

  • сложнее в освоении, чем react-beautiful-dnd;

  • требует работы с useDrag и useDrop, что может быть непривычно.

GitHub:

  • количество звезд: 21,3 тыс.;

  • открытых Issues: 435;

  • версия: 16.0.0;

  • год релиза: 2014;

  • Merge Requests (MRs): основные разработчики и сообщество.

Если нужен гибкий и мощный инструмент для Drag & Drop, React DnD — отличный выбор. Но если задача ограничивается перетаскиванием элементов в списке, лучше использовать react-beautiful-dnd.

Еще о сильных сторонах

В React DnD два основных компонента: DndProvider и DragPreviewImage, — которые позволяют реализовывать различные сценарии.

DndProvider — предоставляет возможности React-DnD для приложения. Должен быть интегрирован в бэкенд через свойство backend, а еще может быть добавлен с помощью объекта window.

Пример использования:

import { HTML5Backend } from 'react-dnd-html5-backend' import { DndProvider } from 'react-dnd'  export default class YourApp {   render() {     return (       <DndProvider backend={HTML5Backend}>         /* Ваше Drag-and-Drop приложение */       </DndProvider>     )   } }

DragPreviewImage — компонент, который отрисовывает HTML-изображение в качестве отсоединяемого перетаскиваемого предварительного просмотра:

import { DragSource, DragPreviewImage } from 'react-dnd'  function DraggableHouse({ connectDragSource, connectDragPreview }) {   return (     <>       <DragPreviewImage src="sun_dragged.png" connect={connectDragPreview} />       <div ref={connectDragSource}>☀️</div>     </>   ) } export default DragSource(   /* ... */   (connect, monitor) => ({     connectDragSource: connect.dragSource(),     connectDragPreview: connect.dragPreview()   }) )

Advanced Cropper

Advanced Cropper — библиотека для точного кадрирования изображений в React. Она дает гибкие инструменты для масштабирования, вращения, зума и ограничения областей обрезки. Поддерживаются touch-жесты, что пригодится для мобильных устройств.

Главное преимущество Advanced Cropper — высокая точность и возможность глубокой кастомизации. Можно задавать фиксированные пропорции, управлять ограничениями области обрезки и добавлять пользовательские элементы управления. Библиотека поддерживает canvas-отрисовку, что делает ее производительной даже при работе с большими изображениями.

Плюсы:

  • поддержка зума, вращения и ограничения области обрезки;

  • гибкость: можно настраивать взаимодействие и UI под свои нужды;

  • хорошо адаптирован для мобильных устройств.

Минусы:

  • требует работы с canvas, если нужна глубокая кастомизация;

  • не самый легковесный вариант.

GitHub:

  • количество звезд: 763; 

  • открытых Issues: 23;

  • версия: 0.20.1;

  • год релиза: 2021;

  • Merge Requests (MRs): главный разработчик и сообщество.

Если в проекте требуется продвинутая обрезка изображений с точными настройками, Advanced Cropper — отличный выбор. 

Еще о сильных сторонах

Для использования нужно добавить в приложение такой код:

import React, { useState } from 'react'; import { CropperRef, Cropper } from 'react-advanced-cropper'; import 'react-advanced-cropper/dist/style.css'  export const GettingStartedExample = () => {     const [image, setImage] = useState( 'https://cdn.prod.website-files.com/65cb50148a423f63add18bc6/65ce1bf224944099ef1159b3_habr.png',     );      const onChange = (cropper: CropperRef) => {         console.log(cropper.getCoordinates(), cropper.getCanvas());     };      return (         <Cropper             src={image}             onChange={onChange}             className={'cropper'}         />     ) };

На колесико мыши работает зум:

React Resizable Panels

React Resizable Panels — библиотека для создания изменяемых по размеру панелей в React-приложениях. Позволяет перетаскивать границы между панелями, менять их ширину или высоту. Отмечу еще гладкие анимации и отзывчивый интерфейс.

В отличие от ручной реализации через div и onMouseMove, библиотека решает все проблемы с перерисовкой, управлением состоянием и совместимостью с адаптивным дизайном. Можно легко создавать гибкие лейауты, включая боковые панели, редакторы с разделенными областями и многосекционные дашборды.

Плюсы:

  • простая интеграция и декларативный API;

  • поддержка горизонтального и вертикального изменения размеров;

  • хорошо работает с анимациями и адаптивным дизайном.

Минусы:

  • подходит только для работы с панелями, для сложных лейаутов может потребоваться CSS Grid или Flexbox.

GitHub:

  • количество звезд: 4,3 тыс.;

  • открытых Issues: 17;

  • версия: 2.1.7;

  • год релиза: 2022;

  • Merge Requests (MRs): главный разработчик и сообщество.

Если нужно удобное изменение размеров панелей без боли, React Resizable Panels — хорошее решение. Оно идеально для редакторов кода, дашбордов и приложений с гибкой компоновкой.

Еще о сильных сторонах

В React Resizable Panels можно создать горизонтальный и вертикальный макеты. Сначала о первом:

<PanelGroup direction="horizontal">  <Panel defaultSize={30} minSize={20}>    left  </Panel>  <PanelResizeHandle />  <Panel minSize={30}>    middle  </Panel>  <PanelResizeHandle />  <Panel defaultSize={30} minSize={20}>    right  </Panel> </PanelGroup>

Чтобы изменить размер, нужно кликнуть на пустое пространство между панелями и зажать левую кнопку мыши. Потом двигать курсор влево или вправо — будет меняться размер панелей:

Теперь про вертикальный:

<PanelGroup direction="vertical">  <Panel maxSize={75}>    top  </Panel>  <PanelResizeHandle />  <Panel maxSize={75}>    bottom  </Panel> </PanelGroup>

Принцип работы тут похожий:

ShadCN UI

ShadCN UI — коллекция UI-компонентов для React, созданная поверх Radix UI и стилизованная с помощью Tailwind CSS. В отличие от традиционных библиотек компонентов (например, MUI или Ant Design), ShadCN не поставляется как отдельный npm-пакет, а предлагает компоненты в виде кода, который можно скопировать в свой проект и кастомизировать.

Главная идея ShadCN UI — гибкость и контроль. Вместо жестко заданных стилей и ограничений — готовые элементы, их легко адаптировать под дизайн системы. Они выглядят минималистично и отлично вписываются в проекты, использующие Tailwind CSS. В библиотеке есть кнопки, поля ввода, диалоги, таблицы, дропдауны и другие базовые элементы UI.

Плюсы:

  • полный контроль над кодом компонентов, их можно редактировать под себя;

  • использует Radix UI, что дает доступность (a11y) и хорошую семантику;

  • отлично совместим с Tailwind CSS;

  • минималистичный дизайн, легко адаптировать под кастомный UI.

Минусы:

  • нужно вручную копировать и поддерживать компоненты в проекте;

  • не такая богатая экосистема, как у Ant Design или MUI;

  • может не подойти, если нужен полный набор готовых решений «из коробки».

GitHub:

  • количество звезд: 83,6 тыс.;

  • открытых Issues: 840;

  • версия: 2.3.0;

  • год релиза: 2023;

  • Merge Requests (MRs): основные разработчики и сообщество. 

ShadCN UI — хороший выбор для тех, кто хочет гибкость Tailwind CSS, удобство Radix UI и контроль над кодом компонентов. Это отличный вариант для кастомных дизайн-систем и современных React-приложений.

Еще о сильных сторонах

В ShadCN UI имеется целый набор готовых компонентов: Accordion (не музыкальный инструмент аккордеон, а вертикально расположенный набор интерактивных заголовков, в каждом из которых находится свой контент), Alert, Card, Chart, Checkbox, Data Table, Dialog, Drawer, Menubar и другие.

Чтобы создать Menubar, необходимо добавить импорты:

import {   Menubar,   MenubarContent,   MenubarItem,   MenubarMenu,   MenubarSeparator,   MenubarShortcut,   MenubarTrigger, } from "@/components/ui/menubar"

И использовать такую структуру:

<Menubar>     <MenubarMenu>         <MenubarTrigger>File</MenubarTrigger>         <MenubarContent>             <MenubarItem>                 New Tab <MenubarShortcut>⌘T</MenubarShortcut>             </MenubarItem>             <MenubarItem>New Window</MenubarItem>           <MenubarSeparator />            <MenubarItem>Share</MenubarItem>             <MenubarSeparator />             <MenubarItem>Print</MenubarItem>         </MenubarContent>     </MenubarMenu> </Menubar>

Пример, как выглядит компонент Menubar:

На сегодня все. Сейчас думаю еще над парой подборок с хорошо зарекомендовавшими себя инструментами. Добавляйте в комментариях, чем пользуетесь вы, — это сделает пост еще полезнее!


ссылка на оригинал статьи https://habr.com/ru/articles/892964/