<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[React хуки: кастомный useFlyMotion для анимаций как в Fly]]></title><description><![CDATA[<p dir="auto">Кастомный хук <strong>useFlyMotion</strong> упрощает создание плавных анимаций в React, вдохновлённых стилем Fly-приложения. Он использует react-spring для реалистичных переходов элементов, таких как списки или модалки. Это решает проблему сложных настроек анимаций вручную.</p>
<p dir="auto">С ним вы быстро добавите <strong>fly-подобные эффекты</strong> — лёгкие появления, исчезновения и перемещения. Подходит для списков задач, карточек или уведомлений. Давайте разберём, как это работает на примерах.</p>
<h2>Что такое useFlyMotion и зачем он нужен</h2>
<p dir="auto">Кастомный хук <strong>useFlyMotion</strong> — это обёртка над хуками react-spring, которая имитирует фирменные анимации Fly: быстрый старт, плавный полёт и мягкую остановку. Представьте список сообщений, где новые элементы “влетают” слева или сверху, а старые выезжают вправо. Без такого хука приходится комбинировать useSpring, useTransition и useChain вручную — это часы кода.</p>
<p dir="auto">В реальных проектах это упрощает <strong>анимацию списков</strong> и модальных окон. Например, в таск-менеджере карточки задач плавно сдвигаются при добавлении новой. Хук берёт на себя расчёт траекторий, скорости и callbacks, оставляя вам только данные. Логично перейти к примерам: вот как он решает типичные задачи.</p>
<ul>
<li><strong>Плавное появление элементов</strong>: Хук автоматически анимирует opacity и transform для входа.</li>
<li><strong>Сдвиги по осям</strong>: Поддержка направлений (слева, справа, сверху) через config.</li>
<li><strong>Синхронизация анимаций</strong>: Встроенный useChain для цепочек эффектов.</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Параметр</th>
<th>Описание</th>
<th>Пример</th>
</tr>
</thead>
<tbody>
<tr>
<td>elements</td>
<td>Массив элементов для анимации</td>
<td><code>[{id: 1, content: 'Задача'}]</code></td>
</tr>
<tr>
<td>direction</td>
<td>Направление полёта</td>
<td><code>'left'</code>, <code>'right'</code>, <code>'up'</code></td>
</tr>
<tr>
<td>reset</td>
<td>Сброс анимации при повторном запуске</td>
<td><code>true</code></td>
</tr>
</tbody>
</table>
<h2>Как реализовать базовый useFlyMotion</h2>
<p dir="auto">Реализация начинается с импорта хуков из <strong>react-spring</strong>. Хук принимает элементы, уникальные ключи и объект конфигурации для анимации. Внутри мы используем useTransition для монтирования/размонтирования, а useSpring — для базовых свойств вроде позиции и прозрачности. Это даёт эффект “полёта”: элементы стартуют с отрицательного translateX/Y и плавно прилетают.</p>
<p dir="auto">Пример: список уведомлений, где новое сообщение влетает справа. Хук возвращает массив анимированных стилей, готовых к применению в map(). Без него пришлось бы писать отдельные анимации для enter/exit. Теперь посмотрим код шаг за шагом.</p>
<pre><code class="language-javascript">import { useTransition, animated, config } from '@react-spring/web';

function useFlyMotion(elements, direction = 'left', reset = true) {
  return useTransition(elements, {
    keys: item =&gt; item.id,
    from: getFromStyles(direction),
    enter: getEnterStyles(direction),
    leave: { opacity: 0, transform: 'translateX(100%)' },
    config: config.gentle,
    reset,
  });
}

function getFromStyles(dir) {
  switch (dir) {
    case 'right': return { opacity: 0, transform: 'translateX(100%)' };
    case 'up': return { opacity: 0, transform: 'translateY(-100%)' };
    default: return { opacity: 0, transform: 'translateX(-100%)' };
  }
}

function getEnterStyles(dir) {
  return { opacity: 1, transform: 'translateX(0%)' };
}
</code></pre>
<ul>
<li><strong>from/enter/leave</strong>: Определяют старт, цель и выход анимации.</li>
<li><strong>config.gentle</strong>: Делает движение пружинистым, как в Fly.*</li>
<li><strong>keys</strong>: Уникальные ID для отслеживания изменений.*</li>
</ul>
<h2>Пример использования в списке карточек</h2>
<p dir="auto">Теперь применим хук к списку задач. Компонент хранит массив объектов с id и текстом. При добавлении новой задачи старые сдвигаются, а новая влетает. useFlyMotion берёт state напрямую, возвращая transitions — массив с style и item. В рендере маппим их на animated.div.</p>
<p dir="auto">Это решает проблему <strong>лагающих списков</strong> при частых обновлениях. React-spring оптимизирует FPS, а хук добавляет визуальный polish. Вот полный компонент:</p>
<pre><code class="language-javascript">import { useState } from 'react';
import { useFlyMotion } from './useFlyMotion';

function TaskList() {
  const [tasks, setTasks] = useState([
    { id: 1, text: 'Сделать кофе' },
    { id: 2, text: 'Проверить почту' },
  ]);

  const transitions = useFlyMotion(tasks, 'right');

  const addTask = () =&gt; {
    setTasks([...tasks, { id: Date.now(), text: `Задача ${tasks.length + 1}` }]);
  };

  return (
    &lt;div&gt;
      &lt;button onClick={addTask}&gt;Добавить задачу&lt;/button&gt;
      {transitions((style, item) =&gt; (
        &lt;animated.div style={style} className="task-card"&gt;
          {item.text}
        &lt;/animated.div&gt;
      ))}
    &lt;/div&gt;
  );
}
</code></pre>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Сценарий</th>
<th>Эффект</th>
<th>Преимущество</th>
</tr>
</thead>
<tbody>
<tr>
<td>Добавление</td>
<td>Влет справа</td>
<td>Плавный shift без рывков</td>
</tr>
<tr>
<td>Удаление</td>
<td>Вылет слева</td>
<td>Не блокирует UI</td>
</tr>
<tr>
<td>Множество</td>
<td>Цепочка анимаций</td>
<td>useChain внутри</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Ключевой нюанс</strong>: Всегда используйте уникальные <em>id</em> — иначе анимации сломаются при реордеринге.*</p>
<h2>Расширения хука для продвинутых эффектов</h2>
<p dir="auto">Базовый хук легко доработать под <strong>FLIP-технику</strong> (First, Last, Invert, Play). Добавьте callback onRest для логики после анимации. Или интегрируйте useSpring для отдельных свойств, как scale или rotate. Например, для модалки: комбинируйте с backdrop-анимацией через useChain.</p>
<p dir="auto">В сложных случаях хук принимает config как проп: { tension: 170, friction: 26 }. Это копирует физику Fly. Аргумент reset=true сбрасывает анимацию при каждом обновлении — идеально для динамических списков. Логично разобрать варианты кастомизации.</p>
<ul>
<li><strong>Интеграция useChain</strong>: Цепочка для фона + контента модалки.</li>
<li><strong>Направления полёта</strong>: ‘left’, ‘right’, ‘up’, ‘down’ с разными from/enter.</li>
<li><strong>Callbacks</strong>: onStart/onRest для side-effects, как фокус после анимации.*</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Хук</th>
<th>Когда использовать</th>
<th>Пример в FlyMotion</th>
</tr>
</thead>
<tbody>
<tr>
<td>useSpring</td>
<td>Один элемент</td>
<td>Scale карточки</td>
</tr>
<tr>
<td>useTransition</td>
<td>Списки</td>
<td>Монтирование задач</td>
</tr>
<tr>
<td>useChain</td>
<td>Последовательность</td>
<td>Backdrop затем контент</td>
</tr>
</tbody>
</table>
<h2>Дальше за пределами базового хука</h2>
<p dir="auto">useFlyMotion покрывает 80% анимаций в стиле Fly, но для gesture-based эффектов (drag-to-dismiss) смотрите Framer Motion. Или комбинируйте с useGesture из react-spring. Осталось поэкспериментировать с physics: меняйте tension/friction под бренд.</p>
<p dir="auto">Другие идеи — анимация роутинга с page transitions или infinite scroll с fade-in. Всё это строится на том же принципе, но требует тюнинга config под производительность.</p>
]]></description><link>https://forum.exlends.ru/topic/416/react-huki-kastomnyj-useflymotion-dlya-animacij-kak-v-fly</link><generator>RSS for Node</generator><lastBuildDate>Sat, 17 Oct 2026 03:12:38 GMT</lastBuildDate><atom:link href="https://forum.exlends.ru/topic/416.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 03 Feb 2026 10:44:18 GMT</pubDate><ttl>60</ttl></channel></rss>