Обработка ошибок в Hooks довольно проста. В этой статье мы продемонстрируем, как в React Hooks происходит обработка ошибок. Для этого нам нужно создать такой механизм, в котором, если ошибка возникает во время работы с компонентом, пользователь должен получить компонент ошибки, а не выбрасывать ошибку времени выполнения из компонента. Будем использовать React Hooks для достижения желаемой функциональности.
Мы создадим простую утилиту для деления двух значений. При этом может возникнуть ситуация, когда пользователю придётся делить число на 0. В этом случае из кода JavaScript должна выбрасываться ошибка, приводящая к появлению исключения времени выполнения.
И вместо безусловного завершения программы (поведение приложения по умолчанию) будет отображаться компонент ошибки Error Component, указывающий на простую ошибку времени выполнения. Вот этот Error Component:
function ErrorComponent() {
return <h1>Division by 0 Error</h1>
}
Это простой компонент, содержащий тег заголовка с сообщением об ошибке. Как только пользователь попытается разделить число на 0, должен отображаться этот компонент.
В приведенном ниже коде мы создаём простую функцию, которая выбрасывает пользовательскую ошибку, когда знаменатель равен 0. В том случае, когда код возвращает пользовательскую ошибку, нам нужно показать ErrorComponent вместо обычного компонента.
function getDivision() {
try {
if (denominator === "0") {
throw new Error("Division By 0");
}
setExecutionOutput(numerator / denominator);
} catch {
// Код обработки ошибок
}
}
Для отслеживания появляющихся ошибок можно использовать переменную состояния. В следующем коде мы создали переменную состояния hasError
. Как только код доходит до блока catch
, мы можем задать этой переменной состояния значение true
:
function getDivision() {
try {
if (denominator === "0") {
throw new Error("Division By 0");
}
setExecutionOutput(numerator / denominator);
} catch {
setHasError(true);
}
}
В этом коде мы из hasError
вызываем функцию-получатель геттер и присваиваем ей значение true
. Теперь всякий раз, когда значение этой переменной будет true
, нужно будет выводить на экран ErrorComponent.
Когда вызывается сеттер setHasError
и ему присваивается значение true
, происходит попытка повторного вывода компонента на экран. При этом мы можем проверить, является ли значение переменной true или false. Если переменная имеет значение true
, отображается ErrorComponent. Вот реализация этого шаблона кода:
<div>
{hasError && <ErrorComponent></ErrorComponent>}
{!hasError && (
<section className="App">
<div>
<label>First Value:{" "}</label>
<input id="firstValue" type="text" value={numerator} onChange={updateValue} />
</div>
<div>
<label>Second Value:{" "}</label>
<input id="secondValue" type="text" value={denominator} onChange={updateValue} />
</div>
<div>Output: {executionOutput}</div>
<input type="button" onClick={getDivision} value="Divide Values" />
</section>
)}
</div>
Здесь мы видим, что если hasError
имеет значение true
, то на экран выводится ErrorComponent. В противном случае отображается обычный HTML-код, принимающий данные пользователя и выдающий результат деления.
Теперь попробуем объединить все эти отдельные блоки в одно целое. Блок для построения кода состоит из:
executionOutput
.hasError
.hasError
помечается как true
.hasError
имеет значение true
, то отображается ErrorComponent.hasError
имеет значение false
, то отображается обычный компонент, принимающий данные пользователя.Далее приводим весь код:
import React, { useState } from "react";
import "./styles.css";
export default function App() {
var [numerator, setNumerator] = useState("");
var [denominator, setDenominator] = useState("");
var [executionOutput, setExecutionOutput] = useState("");
var [hasError, setHasError] = useState(false);
function getDivision() {
try {
if (denominator === "0") {
throw new Error("Division By 0");
}
setExecutionOutput(numerator / denominator);
} catch {
setHasError(true);
}
}
function updateValue(event) {
if (event.target.id === "numerator") {
setNumerator(event.target.value);
} else {
setDenominator(event.target.value);
}
}
return (
<div>
{!hasError && (
<section className="App">
<div>
<label>First Value:{" "}</label>
<input id="firstValue" type="text" value={numerator} onChange={updateValue} />
</div>
<div>
<label>Second Value:{" "}</label>
<input id="secondValue" type="text" value={denominator} onChange={updateValue} />
</div>
<div>Output: {executionOutput}</div>
<input type="button" onClick={getDivision} value="Divide Values" />
</section>
)}
{hasError && <ErrorComponent></ErrorComponent>}
</div>
);
}
function ErrorComponent() {
return <h1>Division by 0 Error</h1>
}
Поэкспериментируйте сами с кодом в этом виртуальном редакторе и попробуйте какой-нибудь сценарий в режиме реального времени:
В целом обработка ошибок и исключений в React не представляет сложностей. Следить за нововведениями в этой области можно по этой ссылке.
Перевод статьи Mayank Gupta: Error Handling in React Hooks
Комментарии