В последнее время начал рассматривать замену ReactJS’y, так как уже немного поднадоело работать с одним и тем же.
Это не значит, что я собираюсь в ближайшее время отказываться от ReactJS и уйти в сварщики.
Я просто считаю, что пользоваться одной технологией всю свою карьеру по причине "ну, она же решает мои задачи", не очень правильным.
Разработчик всегда должен расширять свой кругозор знаний и рассматривать альтернативные технологии, даже если они сегодня тебе и не пригодятся.
И перед дальнейшим прочтением этой заметки просто держите в голове, что это лишь моё субъективное мнение. Через полгода я могу думать о SolidJS совершенно другое, как и о ReactJS.
Итак, раскрою сразу все карты и скажу честно, что на сегодняшний день я не считаю SolidJS лучшей заменой ReactJS’у.
Да, в некоторые местах React значительно уступает Solid’у, особенно в производительности и в размере сборки приложения, но в остальном, это тот же самый React, только со своими особенностями.
И нет, это не опечатка. Все тот же самый JSX и те же функциональные компоненты из ReactJS.
Вот пример уже немного сложней. Реализация счётчика на ReactJS и SolidJS.
Как ты можешь заметить, в SolidJS есть три хука:
createEffect
=> что-то похожее на useEffect
, только зависимости определяет автоматически (их не нужно указывать вторым аргументом в массив). Также, эта функция не умеет определять монтирование и размонтирование, как это делает useEffect
. Для этого есть отдельные хуки.createSignal
=> то же самое, что и useState
onMount
=> хук выполнится при первом рендере компонента.onCleanup
=> хук выполнится при удалении компонента со страницы.Для меня createEffect
выглядит намного удобней и понятней, чем useEffect
, который выполняет роль швеца, жнеца и на дуде игреца.
Программисту меньше приходится думать о зависимостях, из-за которых будет тригериться его хук, так как компилятор SolidJS этот вопрос решает автоматически.
Это, конечно, круто.
Но что если я не хочу следить за всеми зависимостями, что использую в createEffect?
_10const [count1, setCount] = createSignal(0);_10const [count2, setCount] = createSignal(0);_10_10// Что если мне не нужно следить за count1 внутри эффекта?_10createEffect(() => {_10 console.log(count1 + count2);_10});_10_10return <h1>{count1}</h1>
Конечно же на это есть решение, которое, так себе:
_10createEffect(_10 on(count2, (value) => {_10 console.log(value, count1());_10 })_10);
Таким образом, с помощью функции on(...)
эффект будет следить за изменением только count2
.
Уж лучше бы вторым аргумент добавили массив зависимостей 🤷🏻♂️
Не надо привыкать к новому хуку. Работает он точно также, как useState
.
При этом, вторым аргументом можно передавать какие-то опции, которые пока я ещё изучил не полностью.
Также, самый жирный плюс "сигнала" (стейта) в том, что при его изменении, компонент не будет каждый раз вызываться (ререндериться).
Раздражает так называемый "реактивный примитив", который нужно каждый раз вызывать, если необходимо вытащить само значение.
_10const [count1, setCount] = createSignal(0);_10_10// ✅_10return <h1>{count()}</h1>_10_10// ❌_10return <h1>{count}</h1>
Не понимаю, почему нельзя было в своём компиляторе сделать так, чтобы стейт вызывался сам?
Я хочу просто передавать переменную в JSX, как в React'е. Меня бесят эти круглые скобки.
Например, ещё вот. Хоть речь и косвенно затрагивает createSignal
, но все же.
Мы привыкли в ReactJS к тому, что можно внутри функции описать логику фильтрации.
_10const [search, setSearch] = useState('');_10_10const result = items.filter(obj => obj.title.includes(search));_10_10return <ul>{result.map((obj, i) => <li key={i}>{obj.title}</li>)}</ul>
В SolidJS так работать код не будем.
Напомню, что ReactJS при каждом изменении search
будет вызывать наш компонент для отрисовки новых данных.
Но SolidJS вызов функции делает только при первом рендере, что в целом, я считаю хорошим решением.
И тот же самый код из ReactJS, в SolidJS будет выглядеть вот так:
_11const [search, setSearch] = createSignal('');_11_11const result = createMemo(() => items.filter(obj => obj.title.includes(search)));_11_11return (_11 <ul>_11 <For each={result()}>_11 {(obj) => <li>{obj.title}</li>}_11 </For>_11 </ul>_11);
Не могу сказать, что мне не нравится такое решение или наоборот. Почти история о двух стульях.
Я понимаю, что createMemo
тут нужен из-за "особой" реактивности SolidJS.
Но что делать новичку, который первым фреймворком выберет SolidJS?
У нас в реакте до сих пор некоторые "синьоры-помидоры" не разобрались с useMemo / useCallback
, какой ещё createMemo
.
Тут всё нравится. Интуитивно понятные названия у хуков, которые чётко дают тебе понять, какую задачу они выполнят.
Но я бы переименовал onCleanup
в onUnmount
.
Вот тут у React-разработчиков будет бугуртить. Готовы? Точно?
Пропсы нельзя деструктурировать и ты приемный.
_10// ✅_10function Article(props) {_10 return <h1>{props.title}</h1>_10}_10_10// ❌_10function Article({ title }) {_10 return <h1>{title}</h1>_10}
Нифига себе, да! А ты что думал? Деструктризацию он захотел...
Кстати, у Solid'а вообще какой-то фетиш с пропсами:
Не стоит на 100% верить тем красивым графикам и скриншотам, что показывают в других статьях, рассказывая о том, как SolidJS выигрывает в производительности и как мало весит бандл приложения.
Все прочитанные мной статьи "React vs Solid" делают сравнение на каком-нибудь счётчике или тудушке.
И ирония в том, что я тоже сделал сравнение этих двух библиотек, но только на своём пет-проекте.
По факту, это такая ситуативная и спорная фигня с этими сравнениями библиотек.
При дальнейшем чтении, учитывайте, что для более конструктивной оценки необходимо проводить более детальный анализ с бенчмарками и т.п. Я же сделал более поверхностное сравнение.
Вот вам демо-ссылки одного и того же реального пет-проекте на ReactJS и SolidJS.
ReactJS: https://rgxp-react.surge.sh
SolidJS: https://rgxp-solid.surge.sh
Машина: MacBook Air, М1, 8 Гб.
Что делал перед сборкой?
@solidjs/router
и react-router-dom@6
.sass
, reset-css
Итоговые JS-бандлы:
Ниже привожу отчёт по средней оценке производительности двух приложений на ReactJS и SolidJS.
Параметры оценки следующие:
MacBook Air, М1, 8 Гб.
Я переписал 1 пет-проект на SolidJS и не сказать, что сильно впечатлён от рефакторинга.
Из плюсов:
Из минусов:
ReactJS-разработчику будет несложно освоить SolidJS, учитывая его особенности.
Но только после того, как вы закончите изучать React и отточите в нём свои знания, только лишь тогда я бы советовал лезть в изучение SolidJS.
Вакансий по SolidJS пока практически нет (по крайней мере я не встречал за последние полгода).
Пока я не могу для себя назвать SolidJS идеальной заменой ReactJS'y.
Полезные ссылки: