Практический опыт работы с SolidJS

автор red


SolidJS — это уникальный подход к реактивному интерфейсному JavaScript. Он предоставляет компактный набор реактивных «примитивов» и использует их для поддержки функциональности более высокого порядка. Это чем-то похоже на AngularJS и использование ReactiveX, но это совсем другой опыт. SolidJS больше похож на AlpineJS по простоте, но предлагает гораздо более амбициозный набор возможностей.

SolidJS только что выпустил версию 1.0. Давайте взглянем.

Настройка SolidJS

Сначала создайте простой стартовый проект. На локальном компьютере используйте команды из листинга 1, чтобы запустить что-то новое (это соответствует документации SolidJS).

Листинг 1. Создание нового проекта SolidJS

> npx degit solidjs/templates/js my-app
> cd my-app
> npm i # or yarn or pnpm
> npm run dev # or yarn or pnpm

Теперь у вас есть простое приложение SolidJS, работающее. Если вы перейдете по адресу http://localhost:3000, вы увидите целевую страницу.

Обратите внимание, что сервер разработки поддерживает обновления «на лету» (включая горячую замену модулей, HMR). Поэтому, когда вы вносите изменения в файлы, они автоматически обновляют то, что отображается в браузере.

Получение удаленного API с помощью createResource

Начнем с Солида createResource. Это простой слой поверх createSignal, реактивный примитив Solid, обеспечивающий асинхронную связь с удаленными API. Мы собираемся начать здесь, потому что эта функция является ключевым моментом в поддержке Solid приостановки/параллельного рендеринга, и на первый взгляд она может показаться немного непонятной.

В некотором смысле, createResource это средний уровень архитектуры Solid.

Откройте вновь созданную папку в вашей IDE и откройте файл App.jsx. Этот файл загружается как корневой узел вызовом Solid render() метод в index.jsx.

Внесите изменения, которые я прокомментировал в листинге 2.

Листинг 2. Изменение App.jsx

import logo from "./logo.svg";
import styles from "./App.module.css";
import { createResource } from "solid-js";  // Import the createResource function from solid

// The next line sets up the actual async function that will do the request.  It is a simple wrapper around a fetch call that returns a promise - the promise returned by the call to
// fetch.json(). This function is used by the call to createResource below
const fetchJokes = async (id) => (await fetch(`https://official-joke-api.appspot.com/jokes/programming/ten`)).json();

function App() {
  const [jokes] = createResource(fetchJokes);  // Here we use createResource to associate from the fetchJokes promise to the results: the jokes variable

  return (
    <div class={styles.App}>
              <!-- The line below uses the built-in loading state that Solid has provided on the jokes variable, initialized above with a call to createResource -->
      <span>{jokes.loading && "Loading..."}</span>
      <div>
                <!-- This line below simply outputs the contents of the jokes var. This will not happen until jokes.loading == true. >
        <jokes() -->
        <pre>{JSON.stringify(jokes(), null, 2)}</pre>
      </div>
      <header class={styles.header}>
        <img src={logo} class={styles.logo} alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a class={styles.link} href="https://github.com/ryansolid/solid" target="_blank" rel="noopener noreferrer">
          Learn Solid
        </a>
      </header>
    </div>
  );
}

export default App;

Комментарии в листинге 2 должны подсказать вам, что здесь происходит. Результатом работы этого кода является массив JSON, содержащий набор из 10 случайных программных шуток.

Итерация с помощью >For<

Теперь давайте возьмем этот JSON и перейдем по нему, создав более полезный результат.

Во-первых, включите For компонент, добавив его в импорт:

import { createResource, For } from "solid-js";

Затем замените вызов JSON.stringify листингом 3.

Листинг 3. Перебор массива

<ul>
  <For each={jokes()}>{(joke) =>
    <li>{joke.id}: {joke.setup}</li>
  }</For>
</ul>

Листинг 3 дает представление о For компонент в действии. Он похож на другие реактивные фреймворки. Вы указываете ему, какую коллекцию нужно перебирать (т. е. jokes()помня, что это вызов метода, а не ссылка), а затем определите анонимную функцию, аргументом которой является переменная итерации, joke.

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

Обработка событий в SolidJS

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

В листинге 4 показано, как добавить обработчик.

Листинг 4. Обработчик onClick

<li onClick={()=>{alert(joke.punchline)}}>
  {joke.id}: {joke.setup}
</li>

Достаточно просто. Листинг 4 очень типичен для реактивных фреймворков. Теперь, когда я нажимаю «Где любят тусоваться программисты?» Я получаю ответ: «Бар Foo». Это так плохо, что смешно.

Создание реактивных переменных с помощью createSignal

Теперь представьте, что вы хотите добавить возможность переключения между показом программных шуток и всеми шутками. Удаленный API решает эту проблему посредством наличия или отсутствия «программирования» в предпоследней части URL-пути (…/jokes/programming/ten вместо …/jokes/ten).

Итак, давайте добавим флажок в верхней части страницы, чтобы пользователь мог это изменить. Первое, что мы сделаем, это создадим «сигнал». Это самый фундаментальный реактивный примитив в SolidJS. Он позволяет указать переменную, установщик и необязательное значение по умолчанию. Синтаксис вдохновлен useState синтаксис в React.

Над createResource позвоните, добавьте эту строку:

const [jokeType, setJokeType] = createSignal("");

Это создает новый сигнал, называемый jokeType, с начальным значением пустой строки. Доступ к значениям сигналов осуществляется как функция: jokeType().

Теперь вставьте элемент флажка, показанный в листинге 5, в заголовок основного элемента div.

Листинг 5. Реактивный флажок

Programming Only: <input type="checkbox" checked={jokeType()=="programming/"}
        onInput={()=>{setJokeType(jokeType()==''?'programming/':'')}}> </input>

Листинг 5 представляет собой в основном обычный HTML. checked и onInput атрибуты имеют содержимое, специфичное для Solid. checked использует токен для проверки значения jokeType() сигнал против "programming/". То есть флажок устанавливается, если значение jokeType является "programming/".

onInput обрабатывает событие ввода в флажке. Когда он срабатывает, мы меняем значение jokeType так что он переключается между пустой строкой и "programming/". Мы собираемся использовать это изменяющееся значение в URL-адресе средства сбора шуток.

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

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

const [jokes] = createResource(jokeType, fetchJokes); 

(Спасибо Райану Карниато за разъяснение.)

Заметить, что jokeType передается напрямую (не вызов функции, а сама функция). Это связано с тем, что фактический сигнал передается createResourceчто позволяет ему быть реактивным.

Новая функция сбора шуток показана в листинге 6.

Листинг 6. Реактивный ресурс с аргументом сигнала

const fetchJokes = async (jokeType) => {
  return (await fetch(`https://official-joke-api.appspot.com/jokes/${jokeType}ten`)).json();
}

Обратите внимание, что jokeType signal — это прямая переменная в аргументе листинга 6. URL-адрес выборки использует значение jokeType. Когда сигнал изменяется с помощью флажка, Solid заметит это и автоматически повторно получит список шуток.

Вычисленные эффекты с помощью createEffect

Реактивные библиотеки включают возможность обертывания простых реактивных переменных (например, createSignal в SolidJS или useState в React) в так называемом эффекте (например, useEffect в Реакте). Solid обеспечивает createEffect для этой цели. Основная идея заключается в том, что вы используете эффект для обработки нечистых действий (то есть побочных эффектов). Такие действия обычно означают непосредственное изменение некоторой части пользовательского интерфейса в результате изменения переменных, от которых они зависят.

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

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

Листинг 7. Пример createEffect

  createEffect(() => {
    console.log('Joke Type is now: ', jokeType())
  })

Теперь консоль будет выводить данные по мере изменения сигнала. Обратите внимание, что эффект выполняется изначально, когда установлен сигнал.

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

Related Posts

Оставить комментарий