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

В этой статье мы рассмотрим, как можно использовать хук use, чтобы взять целый компонент и сократить его примерно до двух строк кода. Вот насколько силен этот Крюк!
Во-первых, важно понимать, что этот хук довольно новый, и он только в экспериментальной версии React. Итак, вам нужно убедиться, что вы используете экспериментальную версию React и React DOM, чтобы начать пробовать и использовать этот хук.
"dependencies": {
"react": "experimental",
"react-dom": "experimental"
},
И поскольку это экспериментально, это означает, что все может измениться. Если что-то изменится, вы всегда можете узнать больше об этом из документации.
App.tsx
import { useState } from "react"
import { Data } from "./Data"
const URLS = {
USERS:
"https://dummyjson.com/users?limit=3&select=id,firstName,lastName,gender,age",
POSTS: "https://dummyjson.com/posts?limit=3&select=id,title,body",
COMMENTS: "https://dummyjson.com/comments?limit=3",
}
function App() {
const [url, setUrl] = useState(URLS.USERS)
const handleUrlChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setUrl(event.target.value)
}
return (
<div className="App">
<div className="radios">
<label>
<input
type="radio"
value={URLS.USERS}
checked={url === URLS.USERS}
onChange={handleUrlChange}
/>
Users
</label>
<label>
<input
type="radio"
value={URLS.POSTS}
checked={url === URLS.POSTS}
onChange={handleUrlChange}
/>
Posts
</label>
<label>
<input
type="radio"
value={URLS.COMMENTS}
checked={url === URLS.COMMENTS}
onChange={handleUrlChange}
/>
Comments
</label>
</div>
<Data url={url} />
</div>
)
}
export default App
Теперь давайте поговорим о том, что представляет собой этот базовый проект. Мы рассматриваем простой компонент приложения с URL-адресом и тремя переключателями вверху, позволяющими изменить этот URL-адрес.
Data.tsx
import { useEffect, useState } from "react"
interface IProps {
url: string
}
export const Data: React.FC<IProps> = ({ url }) => {
const [isLoading, setIsLoading] = useState(true)
const [isError, setIsError] = useState(false)
const [data, setData] = useState()
useEffect(() => {
setIsError(false)
setIsLoading(true)
setData(undefined)
fetch(url)
.then((res) => res.json())
.then(setData)
.catch(() => setIsError(true))
.finally(() => setIsLoading(false))
}, [url])
return isLoading ? (
<h1>Loading....</h1>
) : isError ? (
<h1>Error</h1>
) : (
<pre>{JSON.stringify(data, null, 2)}</pre>
)
}
Как вы можете видеть, вы ненадолго получаете состояние загрузки, прежде чем оно переместит вас и фактически отобразит данные. Все, что произошло, происходит внутри компонента данных, который имеет простой запрос на выборку.
Когда запрос на выборку возвращает обещание, у нас могут быть либо наши данные, либо ошибка. Мы устанавливаем наше состояние на загрузку, ошибку и данные, затем внутри нашей функции fetch() мы обязательно получаем данные и устанавливаем ошибку, если мы их получаем; если все работает нормально, мы меняем состояние загрузки с false на true, чтобы в случае ошибки отображался значок загрузки.
Это немного громоздко, и работа с чем-либо асинхронным, таким как промисы и React, всегда была серьезной проблемой, но хук use решает все эти проблемы за нас. Мы можем избавиться от всего нашего useState, нашего useEffect и остального нашего кода, поэтому все, что мы делаем, — это простой запрос на выборку.
Data.tsx (после изменения)
import { use } from "react"
interface IProps {
url: string
}
export const Data: React.FC<IProps> = ({ url }) => {
const data = use(fetch(url).then((res) => res.json()))
return <pre>{JSON.stringify(data, null, 2)}</pre>
}
Чтобы использовать хук use, мы передаем ему обещание. Это обещание выборки возвращает либо данные JSON, либо ошибку, которую мы установили в переменную с именем Data. То, как работает этот хук, очень похоже на то, как если бы вы сделали что-то вроде await this fetch, где он даст вам данные или выдаст ошибку, которую вы должны поймать где-то еще.
App.tsx (после изменения)
import { Suspense, useState } from "react"
import { Data } from "./Data"
import ErrorBoundry from "./ErrorBoundary"
const URLS = {
USERS:
"https://dummyjson.com/users?limit=3&select=id,firstName,lastName,gender,age",
POSTS: "https://dummyjson.com/posts?limit=3&select=id,title,body",
COMMENTS: "https://dummyjson.com/comments?limit=3",
}
function App() {
const [url, setUrl] = useState(URLS.USERS)
const handleUrlChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setUrl(event.target.value)
}
return (
<div className="App">
<div className="radios">
<label>
<input
type="radio"
value={URLS.USERS}
checked={url === URLS.USERS}
onChange={handleUrlChange}
/>
Users
</label>
<label>
<input
type="radio"
value={URLS.POSTS}
checked={url === URLS.POSTS}
onChange={handleUrlChange}
/>
Posts
</label>
<label>
<input
type="radio"
value={URLS.COMMENTS}
checked={url === URLS.COMMENTS}
onChange={handleUrlChange}
/>
Comments
</label>
</div>
<ErrorBoundry fallback={<div>{"Error..."}</div>}>
<Suspense fallback={<div>{"Loading..."}</div>}>
<Data url={url} />
</Suspense>
</ErrorBoundry>
</div>
)
}
export default App
Нам нужно обработать загрузку и состояние ошибки, и мы делаем это внутри нашего компонента приложения, используя что-то, что называется приостановкой React. Мы оборачиваем наш дочерний компонент в компонент приостановки, который принимает запасной вариант, и этот запасной вариант будет отображаться каждый раз, когда мы находимся в состоянии загрузки. В противном случае, как только мы закончим загрузку всего, он будет отображать наши данные.
Чтобы поймать ошибки в нашем коде, нам нужно использовать то, что называется границей ошибки. Это особенно часто встречается при работе с саспенсом.
Для начала давайте создадим базовое состояние, чтобы определить, есть ли ошибка, и если да, то что это за ошибка. Затем мы можем получить состояние нашего диска из этой ошибки.
Далее мы будем использовать реквизит под названием «откат» для отображения сообщения об ошибке в случае возникновения ошибки. Если ошибки нет, то мы просто визуализируем все, что находится внутри границы ошибки. Этот подход работает очень похоже на то, как мы справляемся с неизвестностью.
ErrorBoundry.tsx
import React from "react"
class ErrorBoundry extends React.Component {
state = { hasError: false, error: null }
static getDeliveredStateFromError(error: any) {
return {
hasError: true,
error,
}
}
render() {
if (this.state.hasError) {
return this.props.fallback
}
return this.props.children
}
}
export default ErrorBoundry
Внедряя границы ошибок, мы можем гарантировать бесперебойную работу нашего кода и отлавливать любые ошибки, которые могут возникнуть. Итак, в следующий раз, когда вы будете работать с приостановкой или просто захотите быть более активным в отлове ошибок, попробуйте границу ошибки!

Если вы хотите попробовать этот хук use и посмотреть, как он может изменить ваш код, убедитесь, что вы используете экспериментальную версию React и React DOM. С помощью этого хука вы можете сократить весь компонент до двух простых строк, и это все, что нужно для асинхронного кода!