<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>Ихрь постит в уютный бложик: заметки с тегом react</title>
<link>https://ifedyukin.ru/blog/tags/react/</link>
<description>Фрирайтинг, заметки, шитпостинг и все подряд</description>
<author></author>
<language>ru</language>
<generator>Aegea 11.1 (v4098)</generator>

<itunes:subtitle>Фрирайтинг, заметки, шитпостинг и все подряд</itunes:subtitle>
<itunes:image href="" />
<itunes:explicit></itunes:explicit>

<item>
<title>How to inline TailwindCSS styles to SSR NextJS</title>
<guid isPermaLink="false">77</guid>
<link>https://ifedyukin.ru/blog/all/how-to-inline-tailwindcss-styles-to-ssr-nextjs/</link>
<pubDate>Wed, 04 Oct 2023 11:54:42 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/how-to-inline-tailwindcss-styles-to-ssr-nextjs/</comments>
<description>
&lt;p&gt;By default, NextJS may not include Tailwind styles in the SSR build, and with disabled JavaScript, your site may look ugly like pure HTML.&lt;/p&gt;
&lt;p&gt;To fix this, you need to install the &lt;i&gt;critters&lt;/i&gt; package.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;npm install critters&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And enable &lt;i&gt;optimizeCss&lt;/i&gt; rule in &lt;i&gt;next.config.js&lt;/i&gt;.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;experimental: {
    optimizeCss: true,
},&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Source: &lt;a href="https://github.com/vercel/next.js/discussions/12868"&gt;next.js#12868&lt;/a&gt;.&lt;/p&gt;
</description>
</item>

<item>
<title>Как babel-плагин замедлил приложение в 2 раза</title>
<guid isPermaLink="false">55</guid>
<link>https://ifedyukin.ru/blog/all/kak-babel-zamedlil-prilozhenie-v-2-raza/</link>
<pubDate>Thu, 04 Mar 2021 19:11:13 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/kak-babel-zamedlil-prilozhenie-v-2-raza/</comments>
<description>
&lt;p&gt;&lt;b&gt;TL;DR:&lt;/b&gt; в &lt;mark&gt;@babel/plugin-transform-classses&lt;/mark&gt; есть &lt;a href="https://github.com/babel/babel/issues/11356"&gt;баг&lt;/a&gt;, который вызывает падение перформанса.&lt;/p&gt;
&lt;p&gt;Вчера всплыла неожиданная проблема, которая изначально звучала как «часть приложения работает медленнее после оптимизаций сборки проекта». Перформанс панель показывала неутешительные результаты, причем, посмотрев на коллстек, найти даже минимальную зацепку я не смог.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://ifedyukin.ru/blog/pictures/image.png" width="1130" height="293" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Экспериментально удалось выяснить, что проблема возникает чисто из-за каких-то зависимостей.&lt;/p&gt;
&lt;p&gt;С ними в проекте недавно была проведена работа по дедубликации лок-файла и дерева зависимостей, вместе с чем обновились некоторые библиотеки. Минус 7000 строк лока, разбор проблемы обещал быть веселым.&lt;/p&gt;
&lt;p class="note-main"&gt;Проблему искал сначала мой коллега, затем я. Не знаю, сколько времени на это было потрачено, но причиной оказался один плагинчик — &lt;mark&gt;@babel/plugin-transform-classses&lt;/mark&gt;. Откатил версию, зафиксировал ее, и все заработало.&lt;/p&gt;
&lt;p class="note-aside"&gt;Из-за отсутствия зацепок исследование проводилось методом исключения, благо, модули babel были близко к началу очереди.&lt;/p&gt;
&lt;p class="note-main"&gt;Как оказалось, с 1 апреля 2020 года в репозитории есть репорт этой проблемы — &lt;a href="https://github.com/babel/babel/issues/11356"&gt;babel#11356&lt;/a&gt;.&lt;/p&gt;
&lt;p class="note-aside"&gt;Сейчас разбираться, че там внутри плагина поменялось мне лень, конечно, но когда-нибудь обязательно покопаю, когда-нибудь.&lt;/p&gt;
&lt;p&gt;В нашем случае замедление было в среднем в 2+ раза. Некоторым повезло меньше, после обновления Angular можно &lt;a href="https://github.com/angular/angular/issues/41038"&gt;поймать&lt;/a&gt; и более ощутимые просадки.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://ifedyukin.ru/blog/pictures/kak-babel-zamedlil-prilozhenie-v-2-raza.png" width="1199" height="460" alt="Картинка из обсуждения в репозитории Angular'а" /&gt;
&lt;/div&gt;
&lt;p&gt;В очередной раз поймал себя на мысли, что в 2021 году babel уже не нужен. Пора начать выпиливать его из проектов!&lt;/p&gt;
&lt;p&gt;Сейчас придумал теорию заговора, что babel так с адептами ООП борется просто.&lt;br /&gt;
Как там было? Если хочешь, чтобы перестали использовать deprecated метод, добавь в него sleep.&lt;/p&gt;
</description>
</item>

<item>
<title>Ошибки state-менеджмента React-компонентов</title>
<guid isPermaLink="false">49</guid>
<link>https://ifedyukin.ru/blog/all/react-state-issues/</link>
<pubDate>Mon, 15 Jun 2020 19:01:52 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/react-state-issues/</comments>
<description>
&lt;p&gt;При работе с React у многих разработчиков, у которых с ним менее года опыта (или более, но понимания некоторых аспектов нет) возникает проблема с пониманием состояния компонента.&lt;/p&gt;
&lt;p&gt;Когда были классовые компоненты, многие хранили в стейте вообще все, даже какие-то служебные флаги, которые можно было бы в this записать, и которые на рендер компонента никак не влияют.&lt;/p&gt;
&lt;p&gt;Это было проблемой, но решалась она быстро. С появлением хуков ситуация ухудшилась.&lt;/p&gt;
&lt;p&gt;Если в классовых компонентах каждый метод — какой-то шаг лайфсайкла, то с хуками концепция и подход абсолютно другой. Отсюда вырастает много ляпов, которые не сразу заметны и которые разработчики объяснить не могут, но проблемы, возникающие из-за таких ляпов превращаются в серьезную головную боль.&lt;/p&gt;
&lt;p&gt;Парочка самых распространенных, что я видел: Эффект, который слушает проп и обновляет в след за ним стейт без каких-либо преобразований. Что-то вроде такого:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;const component = ({ prop }) =&amp;gt; {
  const [savedProp, setSavedProp] = useState(null);

  useEffect(() =&amp;gt; {
    setSavedProp(prop);
  }, [prop]);
};&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Больше логики никакой, никаких подводных камней. Мало того, что можно было бы прямо в useState прокидывать проп, так все гораздо проще — можно было бы использовать сам этот проп, вместо его сохранения в стейт! Вероятно, там когда-то был какой-то процессинг, может быть, какие-то условия, но больше этого нет, зато есть несколько ненужных обновлений компонента.&lt;/p&gt;
&lt;p&gt;Эффект, который слушает изменения стейта, чтобы… вызвать коллбэк.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;const component = ({ prop, onPropChange }) =&amp;gt; {
  const [savedProp, setSavedProp] = useState(null);

  useEffect(() =&amp;gt; {
    onPropChange(savedProp);
  }, [savedProp]);

  return (
    &amp;lt;Child prop={prop} onPropChange={setSavedProp} /&amp;gt;
  )
};&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Тут все вроде бы тоже понятно, но стейт не используется ни для чего, кроме триггера коллбэка. Правильнее прокинуть просто коллбэк и… все, а не триггерить несколько апдейтов просто так. Так мало того, часто забывают что-то еще в зависимости эффекта прокинуть, и он работает совсем не так, как должен.&lt;/p&gt;
&lt;p&gt;Почему-то за последние полгода столкнулся с кучей таких ошибок, и не только я — в различных чатиках тоже проскакивало частенько. То ли дело в разработчиках, то ли в хуках.&lt;/p&gt;
</description>
</item>

<item>
<title>UI library based on Chakra-UI bundling</title>
<guid isPermaLink="false">47</guid>
<link>https://ifedyukin.ru/blog/all/ui-lib-chakra-bundling/</link>
<pubDate>Thu, 09 Apr 2020 18:49:15 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/ui-lib-chakra-bundling/</comments>
<description>
&lt;p&gt;Recently I tried to build some UI components library that based on &lt;a href="https://github.com/chakra-ui/chakra-ui"&gt;Chakra-UI&lt;/a&gt;. At first my library didn’t contain react components and compiled using typescript and it worked perfectly. But after I added React components based on Chakra-UI and migrated build to webpack, I’ve got the next error from react hooks that were called inside Chakra-UI hooks such as useTheme:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
By the way, Chakra-UI repository has this issue about this error - ((https://github.com/chakra-ui/chakra-ui/issues/495 #495)).&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What is the reason for this error? useTheme hook and Chakra-UI library in whole use react library. As a result library imports react and react-dom. When webpack bundling your library that includes Chakra-UI, it includes react and react-dom to bundle of your library. In brief, you import react to your project, also you import your library with Chakra-UI that contains react too, as a result — you have at least two React copies. And in fact, it’s incorrect hook call.&lt;/p&gt;
&lt;p&gt;How to fix it? Use only single react instance in your app. If you’re using webpack you can mark react and react-dom libraries as external libraries for your components library:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;externals: {
  // mark &amp;quot;react&amp;quot; and react-dom as external packages that will import using commons
  react: 'commonjs react',
  'react-dom': 'commonjs react-dom'
},
output: {
  path: path.resolve('./'),
  libraryTarget: 'commonjs2', // set library target
  filename: '[name].js',
  library: '',
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now bundle of your library doesn’t contain react and react-dom. We marked libraries as external and have pure require calls but doesn’t have library in bundle:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;/***/ &amp;quot;react&amp;quot;:
/*!************************!*\
  !*** external &amp;quot;react&amp;quot; ***!
  \************************/
/*! no static exports found */
/***/ (function(module, exports) {
  module.exports = require(&amp;quot;react&amp;quot;);
/***/ }),

/***/ &amp;quot;react-dom&amp;quot;:
/*!****************************!*\
  !*** external &amp;quot;react-dom&amp;quot; ***!
  \****************************/
/*! no static exports found */
/***/ (function(module, exports) {
  module.exports = require(&amp;quot;react-dom&amp;quot;);
/***/ })&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This way also can help you if you’re using hooks and creating your own UI library without Chakra-UI.&lt;/p&gt;
</description>
</item>

<item>
<title>NextJS, первый взгляд</title>
<guid isPermaLink="false">46</guid>
<link>https://ifedyukin.ru/blog/all/nextjs-begin/</link>
<pubDate>Fri, 28 Feb 2020 18:45:08 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/nextjs-begin/</comments>
<description>
&lt;p&gt;На днях одно (пока) небольшое приложение перевел на NextJS, ибо нужен качественный SSR для SEO, а самостоятельно писать кучу хелперов слишком дорого по времени.&lt;/p&gt;
&lt;p&gt;На первый взгляд все оказалось очень круто, что интересно, почему-то даже некоторые интерактивные элементы начали работать быстрее, не разбирался пока, какая магия их ускорила, но не отметить не мог. Миграция тоже прошла гладко, подключение к проекту было самым крутым из всех инструментов: установить через yarn, удалить конфиг webpack’а, — именно последний пункт больше всего понравился.&lt;/p&gt;
&lt;p&gt;Я сразу подумал, что все слишком хорошо, чтобы быть правдой, в одном чатике отметили, что через недельку я буду бомбить на Next, но пока держусь и странность всего одну заметил — роутинг.&lt;/p&gt;
&lt;p&gt;Казалось бы, роутинг должен быть сильнее всего проработан в фреймворке такого типа, но то ли я не понял, как им правильно пользоваться, то ли оно как-то странно сделано. Ладно, со ссылками пришлось повозиться, ибо в одном случае href — тот url, на который непосредственно идет редирект, а в другом случае — slug страницы, который я определил в роутере, а непосредственно ссылку прокидывать нужно в проп as.&lt;/p&gt;
&lt;p&gt;Но вот если пушить что-то в url с динамическим роутом, то получается что-то странное. Пушу не явный конечный url, а slug описанный в роутинге, нужна квери-стринга? Ок, квери можно прокинуть в отдельный объект, они даже до чилда долетят, но вот в url они не попадут, бери ручками и прокидывай.&lt;/p&gt;
&lt;p&gt;Тут у меня прямо явный диссонанс:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ожидание: сейчас я в метод пуш прокину объект квери и текущий адрес — хоба, квери обновлен, строка адреса хранит состояние, все счастливы.&lt;/li&gt;
&lt;li&gt;Реальность: прокидываю реальный адрес, прокидываю шаблон адреса, прокидываю квери-объект, новый полный адрес вместе с квери, который сам леплю чем-то, — тоже все счастливы, конечно, но большей ценой.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Действий немного, но хотелось бы каких-то изящных абстракций из коробки, а не руками их делать.&lt;/p&gt;
</description>
</item>

<item>
<title>Почему ломаются React-хуки</title>
<guid isPermaLink="false">39</guid>
<link>https://ifedyukin.ru/blog/all/broken-react-hooks/</link>
<pubDate>Fri, 13 Sep 2019 18:18:37 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/broken-react-hooks/</comments>
<description>
&lt;p&gt;В React 16.8 добавили такую крутую фичу, как хуки, все сразу бросились ее юзать, некоторые начали ее юзать еще в бетах, до официального релиза, я же к этой фиче отнесся как-то несколько холодно.&lt;/p&gt;
&lt;p&gt;Без сомнения, идея очень крутая, использовать удобно, можно уходить от классов (я в классах ничего плохого не вижу, но все почему-то это как один из главных пунктов приводят). Но, во-первых, людей надо учить использовать хуки, просто так вот взять и перейти на хуки в production-приложении мне кажется несколько неправильным (какие еще причины, кроме людей, ниже), ибо экспертиза из воздуха не появляется, во-вторых, хуки вносят несколько новых “парадигм”, работу тех же эффектов опять же надо объяснять людям.&lt;/p&gt;
&lt;p&gt;Но пост не о людях, а о самих хуках. На одном из проектиков мы не юзаем хуки, в основном, по причинам, описанным выше, плюс ко всему, основную часть команды составляют малоопытные разработчики, которые только познают все чудеса мира фронтенда, да и сроки слишком сжаты, чтоб в рамках проекта новые техники изучать, но в один момент понадобилось втащить одну библиотеку, которая, как можно догадаться, использует хуки. Да, вот так вот стало сразу модно использовать хуки в библиотеках, не заботясь об обратной совместимости и всяких таких модных важных вещах, при том условии, что хуки там ну чисто для того, чтобы были.&lt;/p&gt;
&lt;p&gt;Втащили библиотеку, заюзали их хуки и… все сломалось, вместо приложения красовалась ошибка:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Конечно, первым делом я перешел по ссылке, проверил версии React’а и всего остального, проверил корректность использования хуков, но все мои исследования пользы не принесли, все было корректно, тогда я пошел шерстить GitHub в поисках решений и источников проблемы.&lt;/p&gt;
&lt;p&gt;Из первого попавшегося &lt;a href="https://github.com/facebook/react/issues/15315"&gt;react#15315&lt;/a&gt;, там виновных нашли сразу кучу, и неправильное использование роутера, и HtmlWebpackPlugin, и вызов в HoC’е, а в &lt;a href="https://ifedyukin.ru/blog/2019/react-dropzone"&gt;react-dropzone#821&lt;/a&gt; вообще оказалось, что все ломали observer’ы из mobx.&lt;/p&gt;
&lt;p&gt;Мой случай похож, хуки ломались из-за использования такой утилиты, как why-did-you-update, которая, к слову, довольно долго жила во многих проектах без проблем, а тут вот всплыло. Соответственно, чтобы поправить работу приложения ни осталось ничего, кроме того, что убрать вызов утилиты.&lt;/p&gt;
&lt;p&gt;Историю свою я рассказал, какой вывод можно сделать? Не знаю, но точно знаю, что хуки с существующими решениями не всегда корректно работают, и что если вдруг хуки сломались надо подчищать HoC’и, несколько часов жизни в никуда...&lt;/p&gt;
</description>
</item>

<item>
<title>React Higher-Order Components</title>
<guid isPermaLink="false">14</guid>
<link>https://ifedyukin.ru/blog/all/react-hoc/</link>
<pubDate>Mon, 24 Jul 2017 17:08:24 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/react-hoc/</comments>
<description>
&lt;p&gt;Несколько расстраивает, что сюда ничего не пишу, так что буду вкидывать какие-то заметки и кусочки кода.&lt;br /&gt;
Начнём с простого и понятного примера &lt;a href="https://facebook.github.io/react/docs/higher-order-components.html"&gt;Higher-Order Components&lt;/a&gt; в React.&lt;/p&gt;
&lt;h3&gt;Enhance.jsx&lt;/h3&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;import { Component } from &amp;quot;React&amp;quot;;

export var Enhance = ComposedComponent =&amp;gt; class extends Component {
  constructor() {
    this.state = { data: null };
  }
  componentDidMount() {
    this.setState({ data: 'Hello, World!!!' });
  }
  render() {
    return &amp;lt;ComposedComponent {...this.props} data={this.state.data} /&amp;gt;;
  }
};&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;HigherOrderComponent.jsx&lt;/h3&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;import { Enhance } from &amp;quot;./Enhance&amp;quot;;

class MyComponent {
  render() {
    if (!this.data) return &amp;lt;div&amp;gt;React loading...&amp;lt;/div&amp;gt;;
    return &amp;lt;div&amp;gt;{this.data}&amp;lt;/div&amp;gt;;
  }
}

export default Enhance(MyComponent);&lt;/code&gt;&lt;/pre&gt;</description>
</item>


</channel>
</rss>