Я пытаюсь создать приложение для реагирования, в котором я извлекаю данные через API, который отлично работает в течение нескольких секунд, а затем я получаю пустой экран и ошибку в консоли, которая выглядит следующим образом:
Консоль : это ошибка консоли браузера
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.
CountryWise.js: это мой компонент, в котором я выполняю все операции.
import React, { useEffect, useState } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
const CountryWise = () => {
const [data, setData] = useState([]);
const [name, setName] = useState("pakistan");
const getCovidData = async () => {
const res = await fetch(
`https://api.covid19api.com/live/country/${name}/status/confirmed`
);
const actualData = await res.json();
setData(actualData);
};
getCovidData();
return (
<>
<div className = "container-fluid mt-5">
<div className = "main-heading">
<h1 className = "mb-5 text-center">Covid-19 Tracker</h1>
<br />
<select
value = {name}
onChange = {(event) => {
setName(event.target.value);
}}
>
<option value = "pakistan">Pakistan</option>
<option value = "afghanistan">Afghanistan</option>
</select>
</div>
<div className = "table-responsive">
<table className = "table table-hover">
<thead className = "table-dark">
<tr>
<th>Country</th>
<th>Date</th>
<th>Active Cases</th>
<th>Confirmed Cases</th>
<th>Deaths</th>
<th>Recovered</th>
</tr>
</thead>
<tbody>
{data.map((curElm, ind) => {
return (
<tr key = {ind}>
<th>{curElm.Country}</th>
<td>{curElm.Date}</td>
<td>{curElm.Active}</td>
<td>{curElm.Confirmed}</td>
<td>{curElm.Deaths}</td>
<td>{curElm.Recovered}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
</>
);
};
export default CountryWise;
App.js: это мое приложение, в котором я визуализирую свой компонент CountryWise.js.
import React from "react";
import CountryWise from "./components/countryWiseData/Countrywise";
function App() {
return <CountryWise />;
}
export default App;
index.js: вот мой файл index.js, в котором я визуализирую компонент приложения.
Существует довольно распространенный хук под названием useIsMounted
, который решает эту проблему (для функциональных компонентов)...
import { useRef, useEffect } from 'react';
export function useIsMounted() {
const isMounted = useRef(false);
useEffect(() => {
isMounted.current = true;
return () => isMounted.current = false;
}, []);
return isMounted;
}
затем в вашем функциональном компоненте
function Book() {
const isMounted = useIsMounted();
...
useEffect(() => {
asyncOperation().then(data => {
if (isMounted.current) { setState(data); }
})
});
...
}
useIsMounted
позволит вам изменить state
только до того, как компонент будет unmounted
из DOM
.
Замените getCovidData()
этим кодом
useEffect(() => {
getCovidData()
}, [name])
Вы получите бесконечный цикл, потому что каждый раз, когда вы вызываете
getCovidData();
, вы вызываетеgetCovidData
, что заставляетCountryWise
снова запускать свое тело, что затем вызываетgetCovidData()
и т. д. Когда ваш компонент размонтируется, ваша выборка все еще происходит в background, и когда он завершается, вызываетсяsetData()
, даже если ваш компонент уже размонтирован