Введение
В дополнение к управлению состоянием и жизненным циклом функциональных компонентов, React Hooks может извлекать код общей логической обработки для использования различными компонентами представления.HOCа такжеRender Propsв основном то же самое. В этой статье в качестве примера будет рассмотрен запрос удаленных данных API, и, наконец, будет извлечен настраиваемый хук для общих запросов данных, чтобы разные компоненты могли совместно использовать набор логики, когда им нужно получить данные.
Применимые считыватели
Предполагаемые читатели этой статьи:
Пример запроса данных
Нажмите кнопку ниже, чтобы просмотреть полный код и рабочий пример этой статьи:
Более полный хук useRequest может относиться к моему проекту с открытым исходным кодом:
нужно
Предположим, у нас есть компонент, которому необходимо одновременно загрузить список сообщений (сообщений в блогах) и задач (todos), каждый из которых отображает 5 заголовков и отображает их в соответствии с состоянием загрузки.loading
компоненты. Сначала мы рассмотрим, как использовать общие хуки.
Определить состояния
Сначала определим необходимые состояния:
// PostsAndTodos.js
const [posts, setPosts] = useState([]);
const [isPostsLoading, setIsPostsLoading] = useState();
const [todos, setTodos] = useState([]);
const [isTodosLoading, setIsTodosLoading] = useState();
-
posts
Используется для сохранения удаленно загруженных данных статьи,isPostsLoading
Сохраните состояние загрузки данных статьи -
todos
сохранить задачи,isTodosLoading
Load - сделайте данные состояния - Здесь мы определяем 4 подобных состояния
Загрузить сообщения
Мы используемuseEffect
запроситьposts
данные:
// PostsAndTodos.js
useEffect(() => {
const loadPosts = async () => {
setIsPostsLoading(true);
try {
let response = await fetch(
"https://jsonplaceholder.typicode.com/posts?_limit=5"
);
let data = await response.json();
setPosts(data);
} catch (e) {
console.log(e);
}
setIsPostsLoading(false);
};
loadPosts();
}, []);
- мы первые
useEffect
Для того, чтобы определитьloadPosts()
Функция запроса удаленных данных. - существует
loadPosts()
В функции в начале запроса мы устанавливаем состояние загрузки вtrue
, в конце, с ошибками или без, установите состояние загрузки вfalse
. - Затем в середине функции мы инициируем запрос на обновление возвращаемых данных до
state
середина.
Загрузить задачи
нагрузкаtodos
код и загрузкаposts
Код в основном такой же, за исключением того, что запрошенныйurl
В отличие от имени функции, которая обновляет состояние:
// PostsAndTodos.js
useEffect(() => {
const loadTodos = async () => {
setIsTodosLoading(true);
try {
let response = await fetch(
"https://jsonplaceholder.typicode.com/todos?_limit=5"
);
let data = await response.json();
setTodos(data);
} catch (e) {
console.log(e);
} finally {
setIsTodosLoading(false);
}
};
loadTodos();
}, []);
Данные дисплея
Здесь мы просто используем<ul>
а также<li>
экспонатposts
а такжеtodos
список:
<div>
<h1>Posts</h1>
<ul>
{isPostsLoading ? (
<div>loading...</div>
) : (
posts.map(post => <li key={post.id}>{post.title}</li>)
)}
</ul>
<h1>Todos</h1>
<ul>
{isTodosLoading ? (
<div>loading...</div>
) : (
todos.map(todo => <li key={todo.id}>{todo.title}</li>)
)}
</ul>
</div>
вопрос
Проблема с этим очевидна, мы по сути дважды повторили логику запроса данных, разница только в запросеurl
, это не соответствует спецификации дизайна многократно используемого кода, и этот компонент переполнен большим количеством кода бизнес-логики и логики отображения, который очень раздут и нарушает принцип проектирования разделения компонентов, то есть компонент, отвечающий за отображение должны быть отделены от кода для бизнес-обработки. Так как его оптимизировать?
Модернизация с пользовательскими крючками
React использует пользовательские хуки, мы можем запросить данные кода, обновить статус загрузки, обновить статус ошибки всех хуков, написанных в пользовательском, затем нужно вызвать сборку, обычно нужна только одна строка кода. Затем переходим к примеру выше.
useRequest
мы создаем новыйuseRequest.js
файл, затем определите функцию с тем же именем:
function useRequest(url) {
// 代码
// return ...
}
React официально рекомендует использовать пользовательские хукиuse
в начале, потому что такое соглашение об именах позволяет человеку, читающему код, знать, что с ним делать. Эта функция имеет следующие характеристики:
- Функции могут принимать аргументы, которые могут быть любыми значениями, необходимыми этому хуку, даже значениями, возвращаемыми другими хуками.
- Функция может иметь возвращаемое значение, которое может использоваться любым компонентом, вызывающим этот хук.
Далее мы пишем свою бизнес-логику, фактически обнаруживая, что первая строка кода в функциональном компоненте заключается в использовании пользовательских хуков.return
Предыдущий код можно напрямую поместить в пользовательские хуки, потому что все они являются бизнес-кодом, иreturn
Код в отвечает за отображение логики.
Копируем и загружаемposts
илиtodos
код дляuseRequest
функция, а затем немного модифицированная:
// useRequest.js
const [data, setData] = useState([]);
const [isLoading, setIsLoading] = useState();
const [error, setError] = useState();
useEffect(() => {
const loadData = async () => {
setIsLoading(true);
try {
let response = await fetch(url);
let data = await response.json();
setData(data);
} catch (e) {
setError(e);
} finally {
setIsLoading(false);
}
};
loadData();
}, []);
return [data, isLoading, error];
Здесь мы изменили наименование состояния и данных на что-то более общее.data
, isLoading
, а такжеerror
, поскольку мы не ограничиваем конкретный домен, любой компонент, которому необходимо загрузить данные, может использовать этот хук. В конце функции возвращаемdata
, isLoading
, error
Эти три состояния используются компонентом, который вызывает этот хук.Требований к типу возвращаемого значения нет.Если возвращаемых значений много, может быть возвращен и объект, например:
return {data, isLoading, error}
Загрузить сообщения и задачи
Теперь давайте посмотрим на код, который снова загружает данные, в новомPostsAndTodosWithHooks.js
файл, нам нужно только вызвать компонентuseRequest
хук для получения данных:
// PostsAndTodosWithHooks.js
const [posts, isPostsLoading] = useRequest(
"https://jsonplaceholder.typicode.com/posts?_limit=5"
);
const [todos, isTodosLoading] = useRequest(
"https://jsonplaceholder.typicode.com/todos?_limit=5"
);
-
useRequest
крючок нуждается вurl
Параметр, адрес запрашиваемых данных. - Мы получаем возвращенные данные и возвращаемое значение состояния загрузки, используем синтаксис ES6 и помещаем
data
а такжеisLoading
псевдоним. - когда
useRequest
Крюкdata
а такжеisLoading
При обновленииPostsAndTodos
Значения, используемые в этих двух состояниях в компоненте, также обновляются синхронно. - Код в части рендеринга компонента остается прежним.
При запуске кода эффект тот же, что и раньше, но код намного проще, хуки и компоненты отображения выполняют свои обязанности, делая код бизнес-логики и представлений понятным и легко читаемым. Более того, повторное использование бизнес-логики также значительно сокращает объем кода, который в данном случае напрямую сокращается на 50%.
государственная изоляция
Некоторым может быть любопытно, не будут ли конфликтовать два вызова одного и того же состояния Hook? еслиposts
После загрузки сначала, затемtodos
Будет ли он перезаписан после завершения загрузкиposts
Данные? Ответ - нет. Все состояния различных вызовов хуков изолированы, даже если один и тот же хук вызывается несколько раз, они сохраняют свое собственное состояние и не влияют друг на друга. Когда состояние в хуке обновляется, оно синхронизируется с компонентом, который его вызвал.
расширять
Вы можете расширить на основе этого примера, например, добавив переменные, такие как метод запроса, заголовок запроса, параметр запроса и т. д., вы также можете добавить кэшированные данные, код для остановки запроса или повторного запуска запроса и обработки событий такие компоненты (например, пейджинг) могут быть определены в пользовательских хуках, а затем все необходимые компоненты (например, пейджинг) могут использовать его для выполнения соответствующей функции.
Суммировать
Пользовательские хуки React предоставляют чрезвычайно важные функции, которые позволяют отделить бизнес-логику от компонентов отображения и использовать ее многократно, что значительно сокращает объем кода и повышает эффективность. Его освоение очень поможет фронтенд-разработке, вот обзор его возможностей и мер предосторожности:
- Пользовательский крючок
use
начало - может принимать параметры
- Может возвращать любой тип возвращаемого значения
- Можно использовать другие встроенные или настраиваемые хуки.
- Каждый раз, когда вызывается хук, состояние и логика в нем изолируются.
Вы научились этому? Если у вас есть какие-либо вопросы, пожалуйста, оставьте сообщение.