Обновить
64K+

ReactJS *

JavaScript-библиотека для создания интерфейсов

21,14
Рейтинг
Сначала показывать
Порог рейтинга

React 19: почему return { error } не предотвращает очистку формы

Форма показывает ошибку сохранения, но введённый текст уже исчез. Такое возможно при использовании функции в action: после её нормального завершения React сбрасывает неконтролируемые поля.

Минимальный пример без сервера — обработчик намеренно всегда возвращает ошибку:

import { useActionState } from "react";

export default function Form() {
  const [state, action] = useActionState(
    async () => ({ error: "Сохранение отклонено" }),
    { error: "" }
  );

  return (
    <form action={action}>
      <label>
        Сообщение
        <textarea name="message" defaultValue="" />
      </label>
      <button type="submit">Сохранить</button>
      {state.error && <p role="alert">{state.error}</p>}
    </form>
  );
}

Введите текст и отправьте форму. Сообщение об ошибке появится, а поле вернётся к пустому defaultValue. Функция завершилась без исключения; свойство error для React — обычные данные, а не указание сохранить содержимое формы.

Один из способов оставить текст для исправления — контролируемое поле с value и onChange. Его состояние можно очищать только после подтверждённого сохранения. Наличие state.error само по себе значениями полей не управляет.

Бросать исключение только ради предотвращения сброса — другая крайность: оно передаёт обработку ближайшему Error Boundary и не заменяет управление черновиком.
Показать ошибку — только половина задачи. Пользователь должен получить возможность исправить уже написанное, поэтому поведение полей при отказе стоит проверять отдельно от сообщения об ошибке.

Итак, вопрос: в ваших тестах формы проверяется, что введённый текст остаётся на месте после неудачного сохранения?

Теги:
0
Комментарии0

Удалили строку в React, а её заметка осталась у другого пользователя

Представим: в списке два человека, у каждого поле для заметки. Вводим «Позвонить вечером» рядом с Анной, удаляем Анну — и видим ту же заметку у Бориса.

Данные людей не перепутаны. Проблема в том, как React сопоставляет строки между рендерами.

Вот компонент, в котором ошибку можно воспроизвести:

import { useState } from "react";

function Row({ person }) {
  const [note, setNote] = useState("");

  return (
    <label>
      {person.name}
      <input
        value={note}
        onChange={event => setNote(event.target.value)}
      />
    </label>
  );
}

export default function App() {
  const [people, setPeople] = useState([
    { id: "anna", name: "Анна" },
    { id: "boris", name: "Борис" }
  ]);

  return (
    <div>
      <button onClick={() => setPeople(p => p.slice(1))}>
        Удалить первого
      </button>
      {people.map((person, index) => (
        <Row key={index} person={person} />
      ))}
    </div>
  );
}

До удаления ключ 0 принадлежит строке Анны. После удаления ключ 0 получает строка Бориса. Для React это тот же компонент на прежнем месте с тем же ключом, поэтому его состояние note сохраняется. При этом person уже содержит Бориса.

Для этого списка исправление выглядит так:

{people.map(person => (
  <Row key={person.id} person={person} />
))}

Теперь у Бориса остаётся собственный ключ boris. При удалении Анны её компонент размонтируется, а состояние строки Бориса сохранится.

Ключ должен быть стабильным для одной записи и уникальным среди соседних элементов. Случайный ключ на каждом рендере тоже создаёт проблему: React будет пересоздавать компоненты, сбрасывая их состояние. Индекс не приводит к ошибке в любом списке, но для списка с удалением, вставкой или перестановкой записей он не сохраняет связь состояния с записью.

Проверить исправление можно в обе стороны: заметка Анны исчезает вместе с Анной, а заметка Бориса остаётся у Бориса после удаления предыдущей строки. Затем стоит повторить проверку с сортировкой списка.

Есть и отдельное ограничение: правильный key не хранит черновик после размонтирования. Если фильтр скрывает Бориса, удаляя его Row из дерева, при возвращении строки локальная заметка начнётся заново. Для сохранения таких черновиков состояние нужно поднять выше и хранить по person.id.

Если при сортировке или удалении элементы будто обмениваются введёнными значениями, стоит проверить ключи до того, как искать ошибку в обработчиках формы.

Теги:
+2
Комментарии0

Таймер работы и отдыха кажется простой задачей, пока не начинаешь хранить его состояние. Я сделал для себя Android-приложение на React Native + Expo и TypeScript. Оно делит рабочий день, например с 9:00 до 18:00, на отрезки работы и отдыха и напоминает о перерывах. Режимов пять: настройка, ожидание начала дня, работа, отдых и окончание дня. На его примере покажу три способа описания состояния, их сильные и слабые стороны. Полный код — на GitHub.

1. Флаги

const [isRunning, setIsRunning] = useState(false);
const [isResting, setIsResting] = useState(false);
const [isFinished, setIsFinished] = useState(false);
  • Три флага дают 8 комбинаций, половина из которых не имеет смысла. Что значит isRunning и isResting одновременно?

  • Правила переходов размазаны по обработчикам: уходя на отдых, нужно не забыть сбросить isRunning.

  • Экран выбирается цепочкой if, и спорную комбинацию решает порядок проверок.

2. Конечный автомат на поле status

type TState = {
  status: 'setup' | 'pending' | 'work' | 'rest' | 'finished';
  dayEndsAt?: number;
  restStartedAt?: number;
  restType?: 'short' | 'long';
};

function reduce(state: TState, event: TEvent): TState {
  switch (state.status) {
    // case 'setup': ... case 'finished': ...
    default: {
      const _exhaustive: never = state.status;
      return state;
    }
  }
}
  • Все режимы перечислены в типе: опечатку 'wrok' или режим, которого нет в списке, компилятор не пропустит.

  • Проверка never в default: если добавить в тип новый режим и забыть обработать его в редьюсере, проект не соберётся.

  • Переходы собраны в одном месте, а всё состояние — один объект, который легко сохранить и восстановить после выгрузки приложения.

Но данные всех режимов лежат в этом объекте необязательными полями.

  • Внутри case 'rest' вид отдыха всё равно может быть undefined, хотя у отдыха он обязан быть всегда, и код обрастает ! и ?..

  • Компилятор пропустит { status: 'work', restType: 'long' }, хотя у работы нет вида отдыха: данные никак не привязаны к режиму.

3. Конечный автомат + размеченное объединение

type TSetup = { state: 'setup' };

type TWork = {
  state: 'work';
  dayEndsAt: number;
  workStartedAt: number;
};

type TRest = {
  state: 'rest';
  dayEndsAt: number;
  restStartedAt: number;
  restType: 'short' | 'long';
};

// TPending и TFinished — аналогично
type TSnapshot = TSetup | TPending | TWork | TRest | TFinished;

Каждый режим описан своим типом со своими полями и общей меткой state. В настройке нет ни конца дня, ни отдыха, а restType и restStartedAt есть только у отдыха.

  • После проверки state TypeScript точно знает, какие поля доступны, и ! с ?. не нужны.

  • «Отдых без времени начала» невозможно даже собрать.

  • Если при переходе забыть перенести поле, это будет ошибка компиляции, а не undefined в рантайме.

  • Цена — многословность: каждый переход заново собирает объект со всеми полями нового режима.

Способы применения

  • Флаги подходят, когда они независимы, например, звук и полноэкранный режим в плеере друг другу не мешают.

  • Поля status без объединения хватит, когда у режимов нет собственных данных.

  • Размеченное объединение нужно, когда у каждого режима свои поля.

XState или свой редьюсер

Для пяти плоских режимов хватает своего редьюсера без зависимостей. Если появятся вложенные или параллельные состояния, отложенные переходы или понадобится визуализация, стоит смотреть на XState.

Технически в приложении расширенный конечный автомат (EFSM). Кроме режимов, он хранит переменные: границы дня, начало текущего отрезка и счётчик рабочих отрезков. На переходах у него есть условия (начать работу можно, только если день ещё не закончился), а сами переходы обновляют переменные. Без переменных пришлось бы плодить состояния WORK_1, WORK_2…

Подробнее:

Теги:
+1
Комментарии0

Поиск в React показывает старый результат. Запросы отправлены правильно, ответы пришли не по порядку

Представьте: пользователь ищет «кот», затем дописывает «котёл». Первый запрос выполняется 1,5 секунды, второй — 100 мс. Сначала появляются результаты для «котёл», затем запоздавший ответ заменяет их результатами для «кот».

Оба запроса успешны. Ошибка в том, что любой ответ получает право обновить экран.

Debounce уменьшает число запросов, но не гарантирует порядок ответов. Уже отправленный медленный запрос всё равно может завершиться последним. Для простого компонента можно совместить отмену запроса с проверкой актуальности его результата.
Ниже хук: query — строка поиска, /api/search — ваш endpoint, возвращающий JSON.

import { useEffect, useState } from "react";

export function useSearch(query) {
  const [state, setState] = useState({ status: "loading" });

  useEffect(() => {
    let active = true;
    const controller = new AbortController();
    setState({ status: "loading" });

    async function load() {
      try {
        const response = await fetch(
          `/api/search?q=${encodeURIComponent(query)}`,
          { signal: controller.signal }
        );
        if (!response.ok) {
          throw new Error(`HTTP ${response.status}`);
        }
        const items = await response.json();
        if (active) setState({ status: "ready", items });
      } catch (error) {
        if (active && error.name !== "AbortError") {
          setState({ status: "error", message: error.message });
        }
      }
    }

    load();
    return () => {
      active = false;
      controller.abort();
    };
  }, [query]);

  return state;
}

У каждого запуска эффекта свой active. При изменении query React очищает предыдущий эффект: старый результат больше не должен менять состояние. Та же проверка стоит в обработке ошибок, иначе запоздавшая ошибка первого запроса может закрыть уже загруженные результаты второго.

AbortController позволяет прекратить ненужный fetch и чтение ответа. Флаг дополнительно защищает обновление состояния. При этом отмена на клиенте не откатывает работу, которую сервер уже успел выполнить.

Для проверки стоит специально задержать первый ответ, быстро изменить запрос и убедиться, что на экране остаются данные второго. Отдельный сценарий — первый запрос завершается ошибкой уже после успешного второго. Механика очистки разобрана в документации React, отмена запроса — в MDN.

Теги:
+2
Комментарии0

Выводим Сову на чистую воду

Небольшой репортаж из самого дружелюбного сообществе, где с уважением относятся к разным точкам зрения:

Упомянутые статьи и выступления:
— Про исправление React
— Про MAM и ESM
— Про SemVer и VerLess
— Про FQN и import
— Про разные виды ссылок
— Про формат Tree

Поблагодарить: https://boosty.to/hyoo
Обсудить: https://t.me/giper_dev

Теги:
0
Комментарии5

Сделал промо-ролик для своего инструмента — и собрал его в Remotion.

Была идея не рисовать интерфейс, а взять уже готовый в Viaduct. Headless Chrome открывает приложение и снимает каждый экран тремя слоями — пустой холст, только связи, полный кадр — и заодно выгружает координаты всех элементов в JSON. Дальше карточки вырезаются из скриншота по этим координатам и выезжают по одной, камера наезжает на нужный элемент, уровни перетекают друг в друга.

Что это даёт: поменялся интерфейс — npm run capture && npm run render, и ролик снова актуален. Нужна локализация — перевести один файл с текстами. Нужна вертикальная версия для Shorts — та же композиция другого размера.

76 секунд, рендер около четырёх минут.

Ролик про Viaduct — браузерный редактор архитектуры по модели C4 с MCP-сервером для кодовых агентов: https://c4.quietgridlabs.com

Если интересно, как устроено внутри — нарезка озвучки по паузам, приглушение музыки под голосом, грабли с headless Chrome — тогда напишу статью с примерами и с готовыми функциями.

Теги:
+2
Комментарии2

React Islands: React-виджеты на чужой HTML-странице

Иногда React нужен не на всю страницу, а точечно: баннер, форма, счётчик. Host при этом — CMS, легаси или другой фреймворк. Поднимать SPA ради пары виджетов избыточно.

Архитектура islands: страница остаётся обычным HTML, а интерактив монтируется отдельными «островами». Библиотека react-islands фиксирует простой контракт: разметка → регистрация → invoke().

Контракт

Host Библиотека data-react-island="<name>" invoke() находит узел и монтирует renderer data-react-island-<attr> уходит в props, если указан в attributes — при mount ставится data-react-island-inited

<div
  data-react-island="banner"
  data-react-island-title="Акция"
  data-react-island-href="/promo"
>
  Fallback до JS
</div>

Использование

import { useEffect } from 'react';
import { Runner, setComponent, getWrapper } from 'react-islands';
import type { ComponentInvokeProps } from 'react-islands';

function Banner({ title, href, innerHTML, onMount }: ComponentInvokeProps & {
  title?: string;
  href?: string;
}) {
  useEffect(() => { onMount?.(); }, [onMount]);

  return (
    <a href={href}>
      <strong>{title}</strong>
      {innerHTML && <span dangerouslySetInnerHTML={{ __html: innerHTML }} />}
    </a>
  );
}

setComponent('banner', (element) => {
  getWrapper({ element, component: Banner, attributes: ['title', 'href'] });
});

Runner.getInstance().invoke();

Повторный invoke() безопасен: already inited узлы пропускаются.

Динамика

const el = document.createElement('div');
el.setAttribute('data-react-island', 'banner');
el.setAttribute('data-react-island-title', 'Ещё баннер');
container.append(el);

runner.render(el);   // смонтировать один
runner.unmount(el);  // снять root перед удалением из DOM
el.remove();

Когда брать

Да: виджеты на CMS/легаси, props из разметки, отдельный bundle островов.
Нет: уже есть React SPA или нужна общая store-шина между виджетами.

Код и демо: gitflic.ru/project/yamakca/react-islands.

Теги:
Всего голосов 1: ↑1 и ↓0+3
Комментарии2

Модель уровня opus 5 бесплатно. swe-2 в devin, но есть нюансыНа выходных многие ломанулись тестировать SWE-2: до 10 октября он бесплатен в Devin Desktop и CLI. Модель интересная: дообученная от Kimi K3, аккуратно правит код, хорошо держит фронт и умеет много агентской рутины. Плюс сразу подхватывает AGENTS.md, skills, MCP и привычные CLI-интеграции. Целей нет, зато есть /loop

Нюанс №1
У части пользователей незаметно включается Adaptive, а по умолчанию рядом маячит Fusion. В итоге ты думаешь, что работаешь на бесплатном SWE-2, а квота уезжает на роутер или lead-модель.В Fusion SWE-2 может быть только допом, а Fable/Astra/Sol платной основой. Дневная квота много у кого горит
Нюанс №2
Бесплатно не значит безлимитно по скорости. По ощущениям, после 5–6 параллельных сессий TPS режется примерно со 100 до 70, в пик может падать до 30. Плюс периодически прилетают 429, и API притормаживает
Чтобы не платить за соседей:

devin --model swe-2-high
/model swe-2-high
/session-stats

В конфиге закрепить (например) %APPDATA%\devin\config.json,

{
  "agent": {
    "model": "swe-2-high"
  }
}

Ну а /fusion, /model adaptive и /handoff не трогать. В статистике должна быть одна модель SWE-2, без Lead/Sidekick, и quota не должна уменьшаться.

P.S. Низкий порог входа по почте и слабая привязка к устройству сделали промо очень удобным для мультиаккаунтинга. Те 1 аккаунт за 20$ на почту + vps + cliproxyapi =>десятки индусов абузят через сабагентов. А еще конечно это по сути бесплатная мощная модель для любых ваших ИИ продуктов

P.P.S. 100% включат недельные квоты для free tier, но попробуй успеть пока не разобрали

Теги:
Всего голосов 1: ↑1 и ↓0+3
Комментарии2

OpenAPI React скомпрометирована в результате атаки на цепочку поставок npm от Mini Shai-Hulud

28 августа 2026 года в npm появились десять вредоносных версий @7nohe/openapi-react-query-codegen. Согласно предупреждению проекта, при установке они запускали код атакующего на машине разработчика или CI-раннере. Под угрозой оказались секреты GitHub, облачных сервисов и реестров пакетов.

За неделю с 23 по 29 августа пакет скачали 156 752 раза. На вредоносные версии пришлось около 1 900 загрузок, и доступны они были меньше двух суток. В пакетной базе npm также находится 8 зависимых пакетов, у которых есть указание использования вредоносного пакета. Это показывает размер потенциально задетой области, а не число подтвержденных заражений.

CodeScoring завел эти версии в базу 29 августа в 02:20 по Москве, через девять минут после публикации предупреждения GitHub, и еще через две минуты они попали под блокировку в платформе. Все десять помечены как опасные, поэтому у пользователей платформы данные компоненты автоматически блокируются при наличии соответствующей политики безопасности.

Атакующему не понадобилось взламывать учетную запись автора пакета. Ошибка была в workflow публикации. Любой пользователь мог открыть pull request из форка и запустить этот сценарий специальным комментарием. GitHub Actions загружал код из pull request и устанавливал зависимости, хотя одновременно имел право публиковать пакет в npm.

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

Вредоносный код запускался во время установки пакета. В части версий запуск был прописан в команде preinstall внутри package.json, которую npm выполняет перед установкой. В других ту же команду спрятали в binding.gyp — конфигурационном файле для сборки нативных модулей с помощью node-gyp. Поэтому проверка только скриптов в package.json не обнаружила бы все зараженные выпуски. Полезная нагрузка искала учетные данные и настройки инструментов разработчика, а затем пыталась распространяться через доступные пакеты и репозитории. Механика похожа на августовскую волну Shai-Hulud, только точкой входа стала не учетная запись мейнтейнера, а небезопасный процесс публикации.

Все зараженные версии при этом получили валидные сведения о происхождении сборки (provenance). Это важная граница такой проверки. Она подтверждает, где собрали и опубликовали пакет, но не доказывает безопасность самого процесса. В данном случае сборка действительно прошла через официальный процесс публикации проекта, который, однако, выполнил код из чужого pull request.

Сейчас основной тег пакета снова указывает на чистую версию 3.0.2, а зараженные релизы удалены из NPM. Удаление пакета из реестра остановит новые установки, но не вернет уже украденные секреты. Командам стоит:

  • проверить файлы зависимостей и SBOM по полному списку зараженных версий;

  • если пакет устанавливался 28 августа с разрешенными установочными скриптами, пересобрать машину или CI-раннер из чистого образа и отозвать секреты, доступные в этой среде;

  • очистить кэш пакетного менеджера и повторить установку с чистой версией;

  • проверить автоматические сценарии публикации: в них нельзя исполнять код из pull request внешних участников с правами на выпуск релизов.

Пользователям CodeScoring достаточно один раз настроить блокирующую политику с условием «Зависимость опасна». Пример настройки данной политики можно найти в документации платформы.

Теги:
Всего голосов 6: ↑6 и ↓0+8
Комментарии0

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

Даже если отправить пол сотни откликов с резюме опытного фронта на hh, с небольшими зарплатными требованиями, не факт, что хоть в одной фирме тебя позовут на собес.

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

Примерно так во многих местах работает найм
Примерно так во многих местах работает найм

Кажется, что квалификация многих новых разрабов, особенно фронтов, сейчас очень низка, также как и тех кто ведёт их найм, и это не в единичных фирмах, я сталкивался с таким в половине мест где я работал.

Также сдаётся мне, что hh совершенно не подходит для поиска работы разработчиком.

В связи с этим хотел бы попросить совета у коллег по цеху, особенно фронтовиков, в форме трех следующих вопросов:
1. Где лучше искать работу, на каком ресурсе?
2. Замечаете ли вы, что hr часто набирают не тех кто реально способен, а тех кто умело врет или красиво улыбается?
3. Стоит ли искать работу фронту или стоит сменить профессию?

Теги:
Всего голосов 5: ↑5 и ↓0+8
Комментарии14

Пока все спорят, Redux или Zustand, я зайду с другой стороны

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

Написала статью «Хороший код, но плохая архитектура» — про то, как мы все пишем аккуратный, типизированный, красивый код и тихо приходим к файлам, которые страшно даже открывать.

Главный (душный) тезис: самая опасная архитектурная ошибка — это хорошее решение, принятое слишком рано. А ещё там есть госпожа Форма, которая знает слишком много, «умные хуки», незаметно ставшие мини-приложениями, и мемоизация как религия.

Без морали «как надо жить» — скорее честный разговор о том, как мы все так делаем и даже не замечаем.

Заходите читать и спорить в комментариях →
https://habr.com/ru/companies/alfa/articles/1044046/

Теги:
Всего голосов 2: ↑2 и ↓0+5
Комментарии0

Насколько сложный проект можно сделать бесплатно в 2026 году?

Всем привет!
Часто вокруг пишут, как ИИ помогает им «сделать SaaS за выходные», хайпят свои проекты и рассказывают про «миллион фич». Решил я проверить: а что реально можно сделать в 2026 году, если использовать только бесплатные тарифы и не тратить деньги?

Спойлер: получилось достаточно много.

Проект полностью экспериментальный — положится в портфолио.

Я решил сделать большой каталог, и выбрал в качестве товара приложения — PWA приложения — вдохновлялся App Store.

Что в итоге умеет платформа

Для пользователей:

- Личный кабинет с библиотекой своих приложений и избранным

- Можно оставлять комментарии, отзывы, лайки

- Сортировка по категориям, похожим на те, что в App Store

- Поиск приложений умный, использует векторное пространство имен от Google

- Приложения ранжируются по рейтингу — расчет по известной байесовской формуле — учитывает количество установок, отзывов, лайков и качество комментариев

- Задействованы, кажется, все методы установки на топ известных браузеров: от новой (2024) в один клик прямо с нашей платформы — для обладателей Chrome на ПК/Android — до пошаговых интерактивных инструкций в тех браузерах, где установка сложна или запутана

- 20 языков, 2 темы, работает офлайн. Сама платформа — тоже PWA.

Для разработчиков:

- Полноценный кабинет разработчика: управление/настройка приложений

- ИИ-перевод на 20 языков при публикации

- Импорт данных приложения со страниц AppStore и RuStore

- Автогенерация промо-картинки приложения + автопубликация в Pinterest

- Встраиваемый install-скрипт — один тег <script> на сайте разработчика добавляет умную кнопку установки

- 3 разных способа верификации приложений

Контентная часть:

- Масштабируемые промо-лендинги о преимуществах PWA

- Статьи-гайды по установке популярных приложений

- Для админа тоже есть свой интерфейс с множеством настроек

БД (Postgres + pgvector)
Supabase — $0

Серверные функции
Vercel + Edge Functions — $0

Фронтенд
Vercel — $0

ИИ с API (переводы, эмбеддинги)
Gemini — $0

Умный поиск
Google Generative Language API + Gemini

Email
Resend — $0

Авторизация
Supabase Auth (Google, GitHub, Discord, GitLab и др.) — $0

Есть пару оговорок:

- Cursor 20$ в месяц — но я и без проекта его покупал

- и доменное имя wapps.store — 8$ за год. Можно было использовать то, что предоставляет Vercel бесплатно

Меня как фронтенд разработчика впечатлил масштаб бесплатных сервисов — да действительно можно реализовать свою задумку и протестировать её на будущих пользователях.

Однако надо понимать:

- бесплатные тарифы не потянут каких-то весомых нагрузок

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

- ну и времени приходится потратить немало, поэтому стоит подумать несколько раз: нужно ли тебе что-то такое просто «потестировать»

Поделитесь своими примеры или существующими проектами - будет интересно!

Теги:
Всего голосов 1: ↑0 и ↓1-1
Комментарии5

Ближайшие события

Кто такой UX/UI разработчик на практике?

Чем он занимается в реальной приземленной разработке?

P.S. делаю программу для завода и глазам больно от интерфейса

Теги:
Рейтинг0
Комментарии4

Solid.js должен был исправить React…но доказал, что React был прав

Все ругали React за массивы зависимостей, странные хуки и непонятные стадии рендеринга. Возникало чувство, что они усложнили фронтенд и добавили в него отложенную реакцию. Команда Solid.js решила это исправить: убрать лишние рендеры и магию по капоту. Идея была проста — использовать реактивность. Solid создавался, чтобы заменить React, но когда они работали над второй версией, тут они уперлись в проблему, которую невозможно решить — ассинхронность.

Представьте: одни данные загрузились, другие ещё нет. Что покажет интерфейс? Фейковый фронтенд, который обманывает пользователя. React решал это с помощью отложенного обновления. Тогда Solid решили встроить ассинхронность прямо в реактивность. Появилось управление загрузкой, ожиданием и обновлениями — реактивность как она есть. Становится понятно, что и та, и та команда приходят к одному выводу с разных сторон, но Solid делает ее частью системы, засовывает ассинхронность прямо в реактивность и внезапно оказывается, что React не был таким уж и плохим дизайном, просто команда React-а пришла к этой проблеме гораздо раньше, чем остальные.

И главный вопрос: что важнее — устоявшийся подход React или более чистая, но сложная реактивность Solid? Или дело вовсе не в фреймворке, а в том, как ты управляешь асинхронностью?

https://dev.to/playfulprogramming/two-react-design-choices-developers-dont-like-but-cant-avoid-d6g

Подписывайтесь: YouTube | VK | Twitter

Теги:
Всего голосов 2: ↑0 и ↓2-2
Комментарии2

Представлен открытый проект TUI Studio (Visual Terminal UI Designer), среды для визуального проектирования интерфейсов пользователя, работающих в текстовом терминале. Среда позволяет в интерактивном режиме наглядно формировать интерфейс, перетаскивая готовые блоки мышью, редактируя свойства в визуальном режиме и предпросматривая результат на лету. Сформированный макет интерфейса может быть экспортирован для использования во фреймворках Ink, BubbleTea, Blessed, Textual, OpenTUI и Tview.

Решение написано на TypeScript с использованием React, Vite, Zustand, Tailwind CSS и Lucide React. Код распространяется под лицензией MIT. Из особенностей разработки отмечается, что почти весь код TUI Studio написан ИИ‑ассистентом Claude.

В TUI Studio предоставляется более 20 готовых компонентов для формирования интерфейса (кнопки, меню, таблицы, списки, индикатор прогресса, диалоги, всплывающие подсказки и тому подобное) и поддерживается 8 тем оформления, а также светлый и тёмный режим, градиентные заливки, ASCII‑цвета и акцентные цвета. Имеется возможность отката изменений. Доступен интерфейс для создания своих компонентов. Проекты сохраняются в формате JSON.

Теги:
Рейтинг0
Комментарии1

Несколько важных новостей

👀 THE MAIN THING!

Gemini в Chrome.
Google официально встроил Gemini прямо в браузер. Пару дней назад Firefox обьявила о том, что приостанавливает создание AI-браузера из-за недовольства пользователей. Google решила сделать наоборот и начинает Новую эру браузеров".

Вот несколько фичей которые они представили:

  1. Постоянная боковая панель, которая видит все ваши открытые вкладки(максимально 112) и может отвечать по конкретной странице. Звучит на самом деле неплохо, так как меньше нужно будет думать и переключаться, однако есть вопросы с безопасностью. Для серфинга в интернете я думаю всем очень понравится.

  2. Автоматический просмотр. Агент сам будет смотреть ваши вкладки, формы, инфу и будет реализовывать сложные цепочки шагов покупок или заполнения форм регистрации или чего-то еще за вас. Звучит немного фантазийно и сложно, но может в будущем так и будет.

  3. Встроенный Nano Banana. Редактирование и создание изображений прямо в браузере без надобности их сохранять и запускать в Paint.

В целом, шаг в сторону умных браузеров многие предсказывали, но не было понятно как они будут менять на подход к работе в браузере. Одно понятно точно, скоро и разработчикам нужно будет менять свои приложения, верстку, роутинг, стейт-менеджмент, SEO и т.д. Нужно будет менять информационную архитектуру приложений. Об этом еще много напушут...

😍 ЕЩЕ НЕМНОГО ИНТЕРЕСНОГО

Bun ускоряет async/await на 35%.
Bun v1.3.7 обновил JavaScriptCore и дал реальный прирост производительности для async/await операций. Для фронтенд-команд это означает более быстрые билды и CI/CD пайплайны, особенно если вы используете Bun для сборки Next.js или других фреймворков.

Yarn 6 переписывают на Rust.
Yarn делает логичный ход: порт в Rust с фокусом на производительность. Если это действительно ускорит установку зависимостей, это сэкономит часы времени разработчиков в неделю, особенно в больших монорепозиториях. Но скорее всего, они просто не смогли победить pnpm, и решили добиться ускорения засчет нативности Rust. 💪

WSO2 публично прощается с Java, переходит на Go.
Enterprise-компания, которая 20 лет строила middleware на Java, теперь говорит: "Java — не язык будущего для нашей инфраструктуры". Для фронтенд-команд это важно, потому что переход backend на Go означает более быстрые BFF и API, что напрямую влияет на UX наших приложений.

Ryan Carniato выпустил обзор JavaScript-фреймворков на 2026 год.
Автор SolidJS делает традиционный "большой обзор" ландшафта фреймворков. Полезен не из-за "кто победит", а из-за того, как он раскладывает тенденции по направлениям — это помогает планировать, какие технологии изучать команде.

Cloudflare делает microfrontends частью своей платформы.
Ещё один шаг к тому, чтобы "фронтенд как монолитное SPA" оставался больше в учебниках, чем в проде. Если инструменты для microfrontends становятся более доступными, это открывает возможности для разделения фронтенда на независимые части.

Мой телеграм канал, все новые посты там! Подпишись!

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии5

Почему у PWA до сих пор нет полноценного «магазина приложений» — возможно ли это вообще?

Всем привет.

В течение последних месяцев, работая с PWA-приложениями, мы постоянно сталкивались с одним и тем же вопросом:

Почему в 2025 году у PWA до сих пор нет настоящего App Store?

Не просто каталога ссылок, а полноценного магазина приложений — знакомого, вызывающего доверие и понятного обычным пользователям.

При изучении существующих PWA-магазинов и каталогов обнаруживаются одни и те же повторяющиеся проблемы.

⸻

  1. Установка остаётся непонятной для пользователей

Даже сегодня установка PWA вызывает затруднения у обычных пользователей.

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

Во многих PWA-каталогах всё ограничивается текстовой инструкцией — и на этом взаимодействие с сервисом фактически заканчивается.

⸻

  1. Отсутствие доверия

Со стороны пользователя это проявляется в следующем:
• нет содержательных отзывов,
• отсутствует история установок,
• нет ощущения личной библиотеки приложений.

Со стороны разработчиков наблюдаются крайности:
• либо любой может опубликовать приложение без подтверждения права собственности,
• либо проверка обязательна, но сложна и ограничена одним способом (например, через DNS-записи).

В итоге доверие не формируется ни у одной из сторон.

⸻

  1. Разработчики — второстепенные участники экосистемы

Распространённые проблемы:
• медленные и неудобные процессы публикации,
• почти полное отсутствие автоматического заполнения данных из манифеста,
• нехватка инструментов, которые были бы полезны разработчику ещё до установки приложения пользователем.

Экосистема не стимулирует разработчиков поддерживать и развивать свои PWA.

⸻

  1. Интерфейс не воспринимается как «нативный»

Это тонкий, но важный момент.

Если магазин:
• выглядит как обычный веб-сайт,
• не вызывает ассоциаций с App Store или Google Play,

пользователи инстинктивно доверяют ему меньше — даже если сами приложения качественные.

⸻

При этом сами PWA как технология за последние годы заметно повзрослели: офлайн-режим, push-уведомления, installability, Web APIs.
Однако именно слой распространения и доверия остаётся самым слабым звеном.

⸻

Главный вопрос, к которому мы пришли

Возможно ли вообще создать PWA-магазин, который:
• пользователи будут воспринимать как настоящий магазин приложений,
• не станет источником боли для разработчиков,
• сможет устойчиво развиваться, а не быть заброшенным через несколько месяцев?

Или же сама идея магазина PWA в текущей экосистеме изначально ошибочна?

Будет интересно узнать ваш опыт.

Вы публиковали PWA-приложения в существующих магазинах или каталогах?
Что вызывало наибольшие сложности — у разработчиков или у пользователей?

Теги:
Всего голосов 3: ↑3 и ↓0+3
Комментарии10

React One Click Component

Поделюсь самодельным расширением для VS Code, которое позволяет создавать React-компоненты в один клик.

Демонстрация работы расширения
Демонстрация работы расширения

Что умеет:

  • гибкое именование файлов: выбор между PascalCase, camelCase, kebab-case или snake_case для генерируемых файлов;

  • работа с .tsx и .jsx для файлов компонентов, а также .scss, .css, .less и .sass для стилей;

  • редактируемые шаблоны: настройка содержимого генерируемых файлов прямо в VS Code;

  • опциональное создание файлов реэкспорта и стилей.

Более подробный readme на странице расширения, ссылка на исходники там же. На мой взгляд экстешнен написан таким образом, что его довольно легко переписать для любого web-фреймворка.

На всякий случай: ни с какими внешними сервисами и нейронками расширение не взаимодействует)

Теги:
Всего голосов 2: ↑2 и ↓0+4
Комментарии0