Я начал создавать некоторые из своих новых компонентов с новыми и блестящими React Hooks. Но я использовал много асинхронных вызовов API в своих компонентах, где я также показывал счетчик загрузки во время выборки данных. Итак, насколько я понял концепцию, это должно быть правильно:
const InsideCompontent = props => {
const [loading, setLoading] = useState(false);
useEffect(() => {
...
fetchData()
...
},[])
function fetchData() {
setFetching(true);
apiCall().then(() => {
setFetching(false)
})
}
}
Так что это только мое первоначальное представление о том, как это может работать. Просто небольшой пример. Но что произойдет, если родительский компонент теперь изменил условие, что этот компонент размонтируется до завершения асинхронного вызова.
Есть ли какая-то проверка, где я могу проверить, смонтирован ли компонент, прежде чем вызывать setFetching(false) в обратном вызове API?
Или я что-то здесь упускаю?
Вот рабочий пример: https://codesandbox.io/s/1o0pm2j5yq
Обновлено: Здесь действительно не было проблемы. Вы можете попробовать это здесь: https://codesandbox.io/s/1o0pm2j5yq
Ошибка была из-за чего-то другого, поэтому с хуками вам не нужно проверять, смонтирован компонент или нет, прежде чем выполнять изменение состояния.
Еще одна причина его использовать :)
@fard нет, это о хуках реакции, а не о обычных методах жизненного цикла реакции
нет никакой реальной разницы и даже ответы были написаны в крючках
Не могли бы вы объяснить, почему отмена запроса не сработает для вас? Используете ли вы данные где-то еще?
so with hooks you don't need to cancel the asynchronous callback that's what it does automatically. Это не будет сделано автоматически, мы должны сами позаботиться об очистке. (удаление прослушивателей событий, отмена сетевых запросов и т. д.)



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете использовать хук useRef для хранения любого изменяемого значения, которое вам нравится, поэтому вы можете использовать его для переключения переменной isMounted на false, когда компонент размонтирован, и проверить, является ли эта переменная true, прежде чем пытаться обновить состояние.
Пример
const { useState, useRef, useEffect } = React;
function apiCall() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Foo");
}, 2000);
});
}
const InsideCompontent = props => {
const [state, setState] = useState({ isLoading: true, data: null });
const isMounted = useRef(true);
useEffect(() => {
apiCall().then(data => {
if (isMounted.current) {
setState({ isLoading: false, data });
}
});
return () => {
isMounted.current = false
};
}, []);
if (state.isLoading) return <div>Loading...</div>
return <div>{state.data}</div>;
};
function App() {
const [isMounted, setIsMounted] = useState(true);
useEffect(() => {
setTimeout(() => {
setIsMounted(false);
}, 1000);
}, []);
return isMounted ? <InsideCompontent /> : null;
}
ReactDOM.render(<App />, document.getElementById("root"));<script src = "https://unpkg.com/react@16/umd/react.development.js"></script>
<script src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id = "root"></div>м.ч. интересный подход. Я использовал аналогичный подход для своих компонентов класса, и это было бы эквивалентно. Я почему-то думал, что это можно решить проще с помощью крючков.
@Tholle Делать отменяемые обещания проще, чистое решение, предоставленное ребятами из React, и оно отлично работает с хуками reactjs.org/blog/2015/12/16/ismounted-antipattern.htmlgithub.com/facebook/react/issues/5465#issuecomment-157888325
@fard Метод isMounted() - это антипаттерн, да, но сохранение ссылки - это нормально. Введение отменяемой абстракции обещания является излишним во многих ситуациях.
@Tholle, я говорю о последнем разделе> В идеале, любые обратные вызовы должны быть отменены до размонтирования.
Предполагая, что это ошибка, с которой вы столкнулись:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
React жалуется и намекает одновременно. Если компонент необходимо размонтировать, но есть ожидающий сетевой запрос, его следует отменить. Возврат функции изнутри useEffect — это механизм для выполнения любой требуемой очистки (документы).
Основываясь на вашем примере с setTimeout:
const [fetching, setFetching] = useState(true);
useEffect(() => {
const timerId = setTimeout(() => {
setFetching(false);
}, 4000);
return () => clearTimeout(timerId)
})
В случае размонтирования компонента до срабатывания обратного вызова таймер сбрасывается и setFetching вызываться не будет.
Тайм-аут был только для имитации времени запроса API. Но спасибо
Да, это ясно, я просто хотел продемонстрировать, как организовать очистку в этом случае.
Вот хук для извлечения данных, которые мы используем внутри. Он также позволяет манипулировать данными после их извлечения и будет выбрасывать данные, если другой вызов будет сделан до завершения вызова.
https://www.npmjs.com/package/use-data-hook
(Вы также можете просто включить код, если вам не нужен весь пакет)
^ Также это преобразуется в JavaScript, просто удаляя типы.
Он частично вдохновлен эта статья, но с большими возможностями, поэтому, если вам не нужны манипуляции с данными, вы всегда можете использовать решение из этой статьи.
Возможный дубликат Как отменить выборку на componentWillUnmount