Solidjs и React.js — различия и сравнение

Solidjs: Solid — это декларативная библиотека JavaScript для создания пользовательских интерфейсов. Вместо использования виртуального DOM, она компилирует свои шаблоны в реальные узлы DOM и обновляет их с помощью тонких реакций.

React: React — это библиотека JavaScript для создания пользовательских интерфейсов. Она использует Virtual DOM для эффективного обновления и рендеринга нужных компонентов при изменении данных.

Ключевые особенности Solidjs:

  • Точное обновление реального DOM.
  • Ментальная модель Render-once: ваши компоненты — это обычные функции JavaScript, которые запускаются один раз для настройки представления.
  • Автоматическое отслеживание зависимостей: доступ к вашему реактивному состоянию подписывается на него
  • Предоставляет современные возможности фреймворка, такие как JSX, фрагменты, Context, порталы, Suspense, потоковое SSR, прогрессивное увлажнение, границы ошибок и параллельный рендеринг.

Ключевые особенности React:

  • Виртуальный DOM: React использует виртуальный DOM для эффективного обновления и рендеринга.
  • Предоставляет современные возможности фреймворка, такие как JSX, фрагменты, Context, порталы, Suspense, потоковое SSR, прогрессивная гидратация, Error Boundaries и параллельный рендеринг.
  • Поддерживается Facebook и сообществом.

Боковое сравнение Solidjs vs React (функциональный компонент)

Компоненты:

React:

Компоненты React могут быть созданы с использованием синтаксиса на основе классов или синтаксиса на основе функций. Компоненты — это функции, которые возвращают JSX.

// Function-based syntax
const Hello = () => <div>Hello</div>;
Вход в полноэкранный режим Выход из полноэкранного режима
Solidjs:

Компоненты — это функции, возвращающие JSX.

const Hello = () => <div>Hello</div>;
Войти в полноэкранный режим Выход из полноэкранного режима

Примечание: Solidjs и React используют один и тот же JSX для шаблонов.


Состояние: Состояние — это обычный объект JavaScript, который используется для записи и реакции на взаимодействие с пользователем.

React:

Состояние — это обычный объект. Вы можете создать состояние с помощью хука useState. useState принимает состояние по умолчанию в качестве параметра и возвращает массив состояний и функций-установщиков состояний.

const Counter = () => {
  const [count, setCount] = useState(0);
  const increment = () => setCount(count + 1);
  // OR
  const increment = () => setCount((c) => c + 1);
  return (
    <div>
      <h1>{count}</h1>
      <button onClick={increment}>Click</button>
    </div>
  );
};
Вход в полноэкранный режим Выход из полноэкранного режима
Solidjs:

Вы можете создать состояние (сигнал) с помощью хука createSignal. createSignal принимает в качестве параметра состояние (сигнал) по умолчанию и возвращает массив функций-установщиков состояния (сигнала) и состояния (сигнала).

const Counter = () => {
  const [count, setCount] = createSignal(0);
  const increment = () => setCount(count() + 1);
  // OR
  const increment = () => setCount((c) => c + 1);
  return (
    <div>
      <h1>{count()}</h1>
      <button onClick={increment}>Click</button>
    </div>
  );
};
Вход в полноэкранный режим Выход из полноэкранного режима

ПРИМЕЧАНИЕ: React Hooks можно вызывать только внутри корня компонента. Solid createSignal можно использовать вне компонента.

const [count, setCount] = useState(0); // Not allowed
useEffect(() => {}, []); // Not allowed
const Counter = () => {};

const [count, setCount] = createSignal(0); // Allowed
createEffect(() => {}); // Allowed
const Counter = () => {};
Вход в полноэкранный режим Выход из полноэкранного режима

Effects (побочный эффект): Это функция, которая запускается при изменении состояния.

React:

В React мы должны передать массив зависимостей в хук useEffect.

Есть 3 способа сделать это:

  1. Без массива зависимостей (эффект будет вызываться при каждом рендере)
  2. С массивом зависимостей (эффект будет вызываться только при изменении зависимостей)
  3. С пустым массивом зависимостей (эффект будет вызван только один раз).
const Counter = () => {
  const [count, setCount] = useState(0);
  useEffect(() => {
    console.log('I am called on every render');
  });

  useEffect(() => {
    console.log('I am called only when count changes');
  }, [count]);

  useEffect(() => {
    console.log('I am called only once');
  }, []);
  return ...
};
Вход в полноэкранный режим Выход из полноэкранного режима
Solidjs:

В Solidjs нам не нужно передавать массив зависимостей, как в хуке useEffect. Он будет автоматически определять зависимости и вызывать эффект только при изменении зависимостей.

const Counter = () => {
  const [count, setCount] = createSignal(0);
  createEffect(() => {
    console.log('I am called only once');
  });

  createEffect(() => {
    console.log('I am called only when count changes',count());
  });
  return ...
};
Вход в полноэкранный режим Выход из полноэкранного режима

Жизненный цикл: Помогает отслеживать состояние и манипулировать им.

React:
const Counter = () => {
  useEffect(() => {
    console.log('I am called onMount');

    return () => console.log('I am called onUnmount');
  }, []);
  return ...
};
Вход в полноэкранный режим Выход из полноэкранного режима
Solidjs:
const Counter = () => {
  onMount(() => console.log('I am called onMount'));
  onCleanup(() =>  console.log('I am called onUnmount'));
  return ...
};
Войти в полноэкранный режим Выход из полноэкранного режима

Refs: Это способ доступа к элементам DOM.

React:
const Counter = () => {
  const ref = useRef();
  useEffect(() => ref.current.focus(), [ref]);
  return <input ref={ref} />;
};
Вход в полноэкранный режим Выход из полноэкранного режима
Solidjs:
const Counter = () => {
  let ref;
  onMount(() => ref?.focus());
  return <input ref={ref} />;
};
Войти в полноэкранный режим Выход из полноэкранного режима

Реквизиты: Это способ передачи данных компонентам. Это обычный объект JavaScript.

React:

Реквизиты передаются как объект и могут быть деструктурированы.

const Counter = (props) => {
  return <div>{props.count}</div>; // Valid
};

const Counter = ({ count }) => {
  return <div>{count}</div>; // Valid
};
Вход в полноэкранный режим Выход из полноэкранного режима
Solidjs:

Реквизиты передаются как объект и не могут быть деструктурированы.

const Counter = (props) => {
  return <div>{props.count()}</div>; // Valid
};

const Counter = ({ count }) => {
  return <div>{count()}</div>; // Not Valid
};
Вход в полноэкранный режим Выход из полноэкранного режима

Список компонентов/элементов:

React:

Для отображения нескольких списков данных можно использовать функцию map.

const Counter = () => {
  const list = [1, 2, 3];
  return (
    <div>
      {list.map((item) => (
        <div>{item}</div>
      ))}
    </div>
  );
};
Вход в полноэкранный режим Выход из полноэкранного режима
Solidjs:

Для отображения нескольких списков данных можно использовать функцию map или компонент For.

const Counter = () => {
  const list = [1, 2, 3];
  return (
    <>
      {list.map((item) => (
        <div>{item}</div>
      ))}

      <For each={list} fallback={<div>Loading...</div>}>
        {(item) => <div>{item}</div>}
      </For>
    </>
  );
};
Вход в полноэкранный режим Выход из полноэкранного режима

Условный рендеринг: Это способ рендеринга компонента на основе условия.

React:
const Counter = () => {
  const [count, setCount] = useState(0);
  return (
    <div>
      <h1>{count < 5 ? "True Value" : "Falsy Value"}</h1>
      <button onClick={() => setCount(count + 1)}>Click</button>
    </div>
  );
};
Вход в полноэкранный режим Выход из полноэкранного режима
Solidjs:
const Counter = () => {
  const count = 5;
  return (
    <div>
      <h1>{count < 5 ? "True Value" : "Falsy Value"}</h1>
      // OR
      <Show when={count < 5} fallback={<h1>Falsy Value</h1>}>
        <h1>True Value</h1>
      </Show>
    </div>
  );
};
Войти в полноэкранный режим Выход из полноэкранного режима

Примечание: Solidjs не перерисовывает компонент. Он всегда отображает первое оцененное значение.

const Counter = () => {
  const [count, setCount] = createSignal(0);
  const TrueCase = (
    <div>
      <h1>From True Value </h1>
      <button onClick={() => setCount((c) => c + 1)}>Click {count()}</button>
    </div>
  );

  const FalseCase = (
    <div>
      <h1>From False Value</h1>
      <button onClick={() => setCount((c) => c + 1)}>Click {count()}</button>
    </div>
  );

  if (count() < 5) return TrueCase;
  return FalseCase; // Never render this
};

// Solution:
const Counter = () => {
  const [count, setCount] = createSignal(0);
  const TrueCase = (
    <div>
      <h1>From True Value </h1>
      <button onClick={() => setCount((c) => c + 1)}>Click {count()}</button>
    </div>
  );

  const FalseCase = (
    <div>
      <h1>From False Value</h1>
      <button onClick={() => setCount((c) => c + 1)}>Click {count()}</button>
    </div>
  );

  return (
    <Show when={count() < 5} fallback={FalseCase}>
      {TrueCase}
    </Show>
  );
};
Вход в полноэкранный режим Выход из полноэкранного режима

Контекст: Это способ обмена данными между родственными/дочерними компонентами.

React:
const CountContext = React.createContext(0);
const Provider = ({ children }) => {
  const [count, setCount] = useState(0);
  return (
    <CountContext.Provider value={{ count, setCount }}>
      {children}
    </CountContext.Provider>
  );
};

const Counter = () => {
  const { count, setCount } = useContext(CountContext);
  return <h1 onClick={() => setCount((c) => c + 1)}>{count}</h1>;
};

const App = () => {
  return (
    <Provider>
      <Counter />
      <Counter />
    </Provider>
  );
};
Вход в полноэкранный режим Выход из полноэкранного режима

Примечание: можно использовать контекст с useReducer, вместо прямого вызова setCount.

Solidjs:
export const CounterContext = createContext([{ count: 0 }, {}]);
export function CounterProvider(props) {
  const [state, setState] = createStore({ count: props.count || 0 });
  const store = [
    state,
    {
      increment: () => setState("count", (c) => c + 1),
    },
  ];

  return (
    <CounterContext.Provider value={store}>
      {props.children}
    </CounterContext.Provider>
  );
}

const Counter = () => {
  const [state, { increment }] = useContext(CounterContext);
  return <h1 onClick={increment}>{state.count}</h1>;
};

const App = () => (
  <CounterProvider>
    <Counter />
    <Counter />
  </CounterProvider>
);
Войти в полноэкранный режим Выход из полноэкранного режима

Solid предлагает множество других возможностей, таких как хранилище для управления состоянием, более подробную информацию можно найти в документации API.

Живая демонстрация: Демонстрация счетчика


Спасибо, что прочитали 😊

У вас есть вопросы или пожелания? Пожалуйста, оставьте комментарий.


Обязательно к прочтению Если вы еще не
использованиеAsync хука с кэшем
Начало работы с SolidJs — руководство для начинающих
Лучшие практики и паттерны React для сокращения кода
3 шага для создания пользовательской библиотеки управления состоянием с помощью React и Context API
Как отменить Javascript API запрос с помощью AbortController
13 Утилиты Typescript: Шпаргалка для разработчика

Больше материалов на Dev.to.
Ловите меня на Github, Twitter, LinkedIn, Medium и Stackblitz.

Оцените статью
Procodings.ru
Добавить комментарий