Skip to content

Latest commit

 

History

History
225 lines (154 loc) · 12.9 KB

File metadata and controls

225 lines (154 loc) · 12.9 KB
title description
Отладка приложений Preact
Как отлаживать приложения Preact, если что-то идёт не так

Отладка приложений Preact

Preact поставляется с большим количеством инструментов, облегчающих отладку. Они помещены в один пакет — preact/debug.

Они включают интеграцию с нашим собственным расширением Preact Devtools для Chrome и Firefox.

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



Установка

Preact Devtools можно установить через магазин расширений вашего браузера.

После установки нам нужно куда-то импортировать preact/debug, чтобы инициализировать соединение с расширением. Убедитесь, что этот импорт является первым импортом во всем вашем приложении.

@preact/preset-vite автоматически включает пакет preact/debug. Вы можете смело пропустить следующий шаг, если используете его!

Вот пример того, как может выглядеть ваш основной файл приложения.

// Должен быть первый импорт
import 'preact/debug';
import { render } from 'preact';
import App from './components/App';

render(<App />, document.getElementById('root'));

Удаление инструментов разработчика из продакшен-сборки

Большинство упаковщиков позволяют вам удалять код, когда они обнаруживают, что ветвь внутри оператора if никогда не будет задействована. Мы можем использовать это, чтобы включать preact/debug только во время разработки и сохранять эти драгоценные байты при сборке.

// Должен быть первый импорт
if (process.env.NODE_ENV === 'development') {
  // Здесь необходимо использовать require, так как на верхнем уровне
  // разрешены только операторы импорта
  require('preact/debug');
}

import { render } from 'preact';
import App from './components/App';

render(<App />, document.getElementById('root'));

Убедитесь, что переменная NODE_ENV имеет правильное значение в вашем инструменте сборки.

Отладка сигналов

Если вы используете Preact Signals в своём приложении, доступны специализированные инструменты для отладки:

  • Signals Debug — Инструмент разработки, который предоставляет подробный вывод в консоль об обновлениях сигналов, выполнении эффектов и пересчётах вычисляемых значений.
  • Signals DevTools — Визуальный интерфейс DevTools для отладки и визуализации Preact Signals в реальном времени. Его можно встроить прямо на страницу для демонстраций или интегрировать в собственные инструменты.

Примечание: Это инструменты, независимые от фреймворка, из библиотеки Signals. Хотя они отлично работают с Preact, они не являются специфичными именно для Preact.

Предупреждения и ошибки отладки

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

undefined родитель передан в render()

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

// Что получил Preact
render(<App />, undefined);

// против того, что он ожидал
render(<App />, actualDomNode);

Основная причина возникновения этой ошибки заключается в том, что узел DOM не присутствует в момент вызова функции render(). Убедитесь в его существовании.

undefined компонент передан в createElement()

Preact будет выдавать эту ошибку, если вместо компонента передать undefined. Частой причиной этого является смешение дефолтного и именованного экспорта.

// app.js
export default function App() {
  return <div>Hello World</div>;
}

// index.js: Неверно, поскольку в файле `app.js` нет именованного экспорта
import { App } from './app';
render(<App />, dom);

Такая же ошибка будет возникать и в обратном случае. Когда вы объявляете именованный экспорт и пытаетесь использовать его в качестве дефолтного экспорта. Один из быстрых способов проверить это (в случае, если ваш редактор этого не делает) — просто выйти из импорта:

// app.js
export function App() {
  return <div>Hello World</div>;
}

// index.js
import App from './app';

console.log(App);
// Лог: { default: [Function] } вместо компонента

Передача JSX-литерала как JSX дважды

Повторная передача JSX-литерала или компонента в JSX является некорректной и приведет к возникновению данной ошибки.

const Foo = <div>foo</div>;
// Неверно: Foo уже содержит JSX-элемент
render(<Foo />, dom);

Чтобы исправить это, мы можем просто передать переменную напрямую:

const Foo = <div>foo</div>;
render(Foo, dom);

Некорректное вложение таблицы

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

Примечание: В этом контексте strict относится к результату работы HTML-парсера, а не к входным данным. Браузеры достаточно снисходительны и пытаются исправить некорректный HTML, чтобы страницы могли отображаться. Однако для VDOM-библиотек вроде Preact это может создать проблемы, так как исходное содержимое может не совпадать с исправленным браузером результатом, о чем Preact не будет знать.

Например, согласно спецификации элементы <tr> всегда должны быть дочерними для <tbody>, <thead> или <tfoot>. Но если вы поместите <tr> непосредственно внутрь <table>, браузер автоматически обернет его в <tbody>. В результате Preact ожидает структуру <table><tr></tr></table>, но реальная DOM-структура от браузера будет такой: <table><tbody><tr></tr></tbody></table>

Некорректное ref-свойство

Если свойство ref содержит что-то неожиданное, мы выдадим эту ошибку. Сюда входят строковые refs, которые уже давно устарели.

// Верно
<div ref={e => {/* ... */)}} />

// Верно
const ref = createRef();
<div ref={ref} />

// Неверно
<div ref="ref" />

Некорректный обработчик события

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

// Верно
<div onClick={() => console.log("клик")} />

// Неверно
<div onClick={console.log("клик")} />

Хук может быть вызван только из методов рендеринга

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

// Неверно, должно использоваться внутри компонента
const [value, setValue] = useState(0);

// Верно
function Foo() {
  const [value, setValue] = useState(0);
  return <button onClick={() => setValue(value + 1)}>{value}</button>;
}

Получение vnode.[property] устарело

В Preact X мы внесли некоторые изменения в нашу внутреннюю форму vnode.

Preact 8.x Preact 10.x
vnode.nodeName vnode.type
vnode.attributes vnode.props
vnode.children vnode.props.children

Дочерние элементы с одинаковым ключом

Уникальность библиотек, основанных на Virtual DOM, заключается в том, что они должны определять, когда дочерний элемент перемещается. Однако для того, чтобы знать, кто есть кто из дочерних элементов, нам необходимо их как-то помечать. Это необходимо только при динамическом создании дочерних элементов.

// Оба элемента будут иметь одинаковый ключ "A"
<div>
  {['A', 'A'].map(char => <p key={char}>{char}</p>)}
</div>

Правильный способ — дать им уникальные ключи. В большинстве случаев данные, над которыми выполняется итерация, имеют тот или иной вид id.

const persons = [
  { name: 'Джон', age: 22 },
  { name: 'Сара', age: 24 },
];

// Где-то позже в вашем компоненте
<div>
  {persons.map(({ name, age }) => {
    return <p key={name}>{name}, Возраст: {age}</p>;
  })}
</div>;