| title | description |
|---|---|
Отладка приложений 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 обнаруживает недействительный код. Их необходимо исправить, чтобы обеспечить безупречную работу приложения.
Это означает, что код пытается превратить ваше приложение в ничто, а не в узел DOM. Это разница между:
// Что получил Preact
render(<App />, undefined);
// против того, что он ожидал
render(<App />, actualDomNode);Основная причина возникновения этой ошибки заключается в том, что узел DOM не присутствует в момент вызова функции render(). Убедитесь в его существовании.
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 является некорректной и приведет к возникновению данной ошибки.
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 содержит что-то неожиданное, мы выдадим эту ошибку. Сюда входят строковые 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>;
}В 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>;