Реагирование Useffect Крюк отлично подходит для выполнения побочных эффектов в функциональных компонентах. Один общий пример этого получает данные. Если вы не осторожны, чтобы убрать свой эффект, однако, вы можете в конечном итоге с состоянием гонки! В этом посте мы уверенным, что мы соответствующим образом убираем наши эффекты, поэтому у нас нет этой проблемы состояния расы.
Настраивать
В нашем примере приложение мы собираемся поддельные данные профиля людей, когда их имена нажаты. Чтобы помочь визуализировать состояние гонки, мы создадим fakefetch Функция, которая реализует случайную задержку от 0 до 5 секунд.
const fakeFetch = person => {
return new Promise(res => {
setTimeout(() => res(`${person}'s data`), Math.random() * 5000);
});
};
Первоначальная реализация
Наша первоначальная реализация будет использовать кнопки для установки текущего профиля. Мы достигаем Уместите Крюк для реализации этого, поддержание следующих состояний:
человекС человек, выбранный пользователемданныеС данные, загруженные из нашей поддельной выборки на основе выбранного человекаЗагрузка, были ли данные в настоящее время загружены
Мы дополнительно используем Useffect крючок, который выполняет нашу фальшивую выборку всякий раз, когда человек изменения.
import React, { Fragment, useState, useEffect } from 'react';
const fakeFetch = person => {
return new Promise(res => {
setTimeout(() => res(`${person}'s data`), Math.random() * 5000);
});
};
const App = () => {
const [data, setData] = useState('');
const [loading, setLoading] = useState(false);
const [person, setPerson] = useState(null);
useEffect(() => {
setLoading(true);
fakeFetch(person).then(data => {
setData(data);
setLoading(false);
});
}, [person]);
return (
{person && (
{person}
{loading ? 'Loading...' : data}
)}
);
};
export default App;
Если мы запустим наше приложение и щелкните одну из кнопок, наша поддельная выборка загружает данные, как ожидалось.
Ударяя состояние гонки
Беда приходит, когда мы начинаем переключаться между людьми в быстрой последовательности. Учитывая тот факт, что наша фальшивая выборка имеет случайную задержку, мы скоро найдем, что наши результаты Fetch могут быть возвращены из строя. Кроме того, наш выбранный профиль и загруженные данные могут быть вне синхронизации. Это плохой вид!
Что здесь происходит относительно интуитивно понятное: setdata (данные) в пределах Useffect Крючок вызывается только после fakefetch обещание решено. Какое бы это обещание решает последнюю, позвонит Сетдата Последнее, независимо от того, какая кнопка фактически называлась последней.
Отмена предыдущих извлечений
Мы можем исправить это состояние гонки с помощью «отмены» Сетдата Звоните для любых кликов, которые не являются последними. Мы делаем это, создавая логическую переменную, находящуюся в радиусе Useffect Крючок и возвращение функции очистки от Useffect Крюк, который устанавливает эту логию «отмененную» переменную в истинный . Когда обещание решает, Сетдата будет называться только если «отмененная» переменная ложна.
Если это описание было немного запутанным, следующий кодовый образец Useffect крючок должен помочь.
useEffect(() => {
let canceled = false;
setLoading(true);
fakeFetch(person).then(data => {
if (!canceled) {
setData(data);
setLoading(false);
}
});
return () => (canceled = true);
}, [person]);
Даже если предыдущая кнопка щелкает fakefetch Обещание решает позже, его отменено Переменная будет установлена на правда и setdata (данные) не будет выполнен!
Давайте посмотрим, как наши новые функции приложения:
Perfect – независимо от того, сколько раз мы нажимаем на разные кнопки, мы всегда будем только увидеть данные, связанные с последней кнопкой кнопки.
Полный код
Полный код из этого поста блога можно найти ниже:
import React, { Fragment, useState, useEffect } from 'react';
const fakeFetch = person => {
return new Promise(res => {
setTimeout(() => res(`${person}'s data`), Math.random() * 5000);
});
};
const App = () => {
const [data, setData] = useState('');
const [loading, setLoading] = useState(false);
const [person, setPerson] = useState(null);
useEffect(() => {
let canceled = false;
setLoading(true);
fakeFetch(person).then(data => {
if (!canceled) {
setData(data);
setLoading(false);
}
});
return () => (canceled = true);
}, [person]);
return (
{person && (
{person}
{loading ? 'Loading...' : data}
)}
);
};
export default App;
Оригинал: “https://dev.to/nas5w/avoiding-race-conditions-when-fetching-data-with-react-hooks-4pi9”