Перейти к содержанию

FAQ - Часто задаваемые вопросы

JSX без виртуального DOM? Является ли это пародийной идеей? Я слышал, как известные люди говорили, что это невозможно.

Это возможно, если у вас нет модели обновления React. JSX - это шаблонный язык, такой же, как в Svelte или Vue, только более гибкий в некоторых отношениях. Вставка произвольного JavaScript иногда может быть сложной, но ничем не отличается от поддержки операторов разделения. Так что нет: это не пародия, а подход, доказавший свою эффективность.

Реальное преимущество заключается в том, насколько он расширяем. У нас есть компилятор, работающий на вас, чтобы обеспечить оптимальное обновление нативного DOM, но у вас есть вся свобода библиотеки типа React. Вы можете писать компоненты, используя стандартные техники, такие как render props, а также компоненты более высокого порядка наряду с реактивными "хуками". Не нравится, как работает поток управления Solid? Напишите свой собственный.

Почему Solid настолько производителен?

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

  1. Явная реактивность, поэтому отслеживаются только те действия, которые должны быть реактивными.
  2. Компиляция с учетом первоначального создания. Solid использует эвристику и комбинирует нужные выражения, чтобы уменьшить количество вычислений, но сохранить гранулярность и производительность обновления ключей.
  3. Реактивные выражения - это просто функции. Это позволяет использовать "исчезающие компоненты" с ленивой оценкой пропсов, устраняя ненужные обертки и накладные расходы на синхронизацию.

Это уникальные на сегодняшний день технологии в комбинации, которая дает Solid преимущество перед конкурентами.

Существует ли React-Compat, или способ использовать мои библиотеки React в Solid?

Нет. И, скорее всего, никогда не будет. Несмотря на схожесть API и возможность переноса компонентов с незначительными правками, модель обновления принципиально отличается. Компоненты React отрисовываются снова и снова, поэтому код вне хуков работает совсем по-другому. Закрытия и правила хуков не только не нужны в Solid: они могут предписывать код, который здесь не работает.

Vue-Compat, с другой стороны, был бы выполним, хотя в настоящее время его реализация не планируется.

С другой стороны, есть возможность запускать Solid в рамках React. React Solid State делает Solid API доступным в функциональных компонентах React. reactjs-solidjs-bridge позволяет рендерить компоненты React внутри компонентов Solid и наоборот, что полезно при постепенном переносе приложения.

Почему я не должен использовать map в своем шаблоне, и в чем разница между <For> и <Index>?

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

Циклы <For> и <Index> предлагают более умное решение. Они связывают каждый отрисованный узел с элементом массива, поэтому при изменении элемента массива будет перерисовываться только соответствующий узел.

<Index> делает это по индексу: каждому узлу соответствует индекс в массиве; <For> делает это по значению: каждому узлу соответствует часть данных в массиве. Именно поэтому в обратном вызове <Index> выдает сигнал для элемента: индекс для каждого элемента считается фиксированным, но данные по этому индексу могут меняться. С другой стороны, <For> дает сигнал для индекса: содержимое элемента считается фиксированным, но оно может перемещаться, если в массиве перемещаются элементы.

Например, если поменять местами два элемента в массиве, то <For> переместит два соответствующих узла DOM и попутно обновит их сигналы index(). А <Index> не переместит ни одного узла DOM, но обновит сигналы item() для двух узлов DOM и вызовет их рендеринг.

Для более детальной демонстрации разницы смотрите этот сегмент потока Райана.

Почему я теряю реактивность при деструктуризации пропсов?

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

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

В данном примере обращение к свойствам происходит внутри JSX-шаблона, поэтому оно отслеживается, и содержимое span обновляется при изменении сигнала:

1
2
3
4
5
6
7
function BlueText(props) {
    return (
        <span style="color: blue">{props.text}</span> // 👈 tracked
    );
}
// ...
<BlueText text={mySignal()} />;

Но ни в одном из этих примеров текст span не будет обновлен, поскольку обращение к свойству происходит вне шаблона:

1
2
3
4
5
6
function BlueText(props) {
    const text = props.text; // 👈 not tracked
    return <span style="color: blue">{text}</span>;
}
// ...
<BlueText text={mySignal()} />;

1
2
3
4
5
6
7
function BlueText({ text }) {
    return (
        <span style="color: blue">{text}</span> // 👈 not tracked
    );
}
// ...
<BlueText text={mySignal()} />;

Если же вы предпочитаете стиль ранней деструктуризации, то есть два различных преобразования Babel, которые можно использовать для того, чтобы сделать (определенные стили) деструктуризации снова реактивными: babel-plugin-solid-undestructure и Solid Labels' object features.

Почему мой обработчик события onChange не срабатывает вовремя?

В некоторых фреймворках событие onChange для ввода изменяется таким образом, что оно срабатывает при каждом нажатии клавиши. Однако событие onChange работает не так [https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onchange]: оно предназначено для отражения фиксированного изменения значения ввода и обычно срабатывает, когда ввод теряет фокус. Для обработки всех изменений значения ввода используйте onInput.

Можете ли вы добавить поддержку компонентов классов? Я считаю, что жизненные циклы проще для рассуждений.

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

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

Мне очень не нравится JSX, есть ли возможность использовать другой язык шаблонов? О, я вижу у вас есть Tagged Template Literals/HyperScript. Может быть, я буду использовать их...

Мы используем JSX так же, как Svelte использует свои шаблоны, для создания оптимизированных инструкций DOM. Решения Tagged Template Literal и HyperScript могут быть действительно впечатляющими сами по себе, но если у вас нет реальной причины, например, требования запрета на сборку, они уступают во всех отношениях. Более крупные пакеты, более низкая производительность, необходимость ручного обхода обертки значений.

Хорошо, когда есть выбор, но JSX от Solid - это действительно лучшее решение. Шаблонный DSL тоже был бы хорош, хотя и более ограничен, но JSX дает нам так много бесплатно. Существующие парсеры, подсветка синтаксиса, Prettier, завершение кода и, наконец, TypeScript.

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

Когда использовать сигнал или магазин? Почему они отличаются?

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

Как бы нам ни хотелось объединить их в одно целое, вы не можете проксировать примитивные значения, поэтому в данном случае мы используем функции. Любое реактивное выражение (включая доступ к состоянию) может быть обернуто в функцию на транспорте, так что это обеспечивает универсальный API. Вы можете называть свои сигналы и состояния по своему усмотрению, и все это останется минимальным. Последнее, что нам хотелось бы сделать, - это заставить конечного пользователя набирать .get() .set() или, еще хуже, .value. По крайней мере, первые могут быть псевдонимами для краткости, в то время как вторые - это просто наименее лаконичный способ вызова функции.

Почему я не могу просто присвоить значение магазину Solid, как это можно сделать в Vue, Svelte или MobX? Где двусторонняя привязка?

Реактивность - мощный, но и опасный инструмент. MobX знает это и ввел строгий режим и Actions, чтобы ограничить, где/когда происходят обновления. В Solid, который имеет дело с целыми деревьями данных Component, стало очевидно, что здесь мы можем кое-что перенять у React. Вам не нужно быть фактически неизменяемым, если вы предоставляете средства для того, чтобы иметь тот же контракт.

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

Могу ли я использовать реактивность Solid самостоятельно?

Конечно. Хотя мы не экспортировали отдельный пакет, можно легко установить Solid без компилятора и просто использовать реактивные примитивы. Одно из преимуществ гранулярной реактивности заключается в том, что она не зависит от библиотек. По сути, почти каждая реактивная библиотека работает таким образом. Именно это и вдохновило разработчиков Solid и лежащей в его основе библиотеки DOM Expressions на создание рендерера исключительно на основе реактивной системы.

Перечислим некоторые из них: Solid, MobX, Knockout, Svelte, S.js, CellX, Derivable, Sinuous, и даже недавно Vue. Создание реактивной библиотеки требует гораздо больше усилий, чем навешивание тегов на рендерер, например, lit-html, но это хороший способ получить представление.

Есть ли у Solid библиотека, подобная Next.js или Material Components, которую я могу использовать?

Мы работаем над SolidStart, который является нашим стартовым решением для SSR, аналогичным Next.js или SvelteKit.

Что касается библиотек компонентов, то у нас есть SUID - порт Material UI для Solid, Hope UI - решение, похожее на Chakra, Solid Bootstrap и многие другие! Ознакомьтесь с нашей быстро растущей экосистемой библиотек и инструментов.

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

Ссылки

Комментарии