在我请求两个端点并将其存储在一个新的状态变量中后,我将无法在状态更改后呈现组件。当我将状态变量指定给useEffect的依赖数组时,它会无限渲染。
我尝试了一些方法,但在组件加载后,我能做的唯一方法就是将合并状态添加到依赖数组中。
import { ChangeEvent, FC, useEffect, useState } from "react";
import spacex from "../api/spacex";
import CardGrid from "../components/CardGrid";
import Header from "../components/Header";
import Pagination from "../components/Pagination";
import SkeletonGrid from "../components/SkeletonGrid";
type Launch = {
mission_name: string;
};
const LaunchesMain: FC = () => {
const [launches, setLaunches] = useState<any>([]);
const [rockets, setRockets] = useState<any>([]);
const [merged, setMerged] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [postsPerPage, setPostsPerPage] = useState(9);
const [searchTerm, setSearchTerm] = useState("");
const [filteredResult, setFilteredResult] = useState([]);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const fetchRockets = async () => {
const responseRocket = await spacex.get("/rockets");
const responseLaunches = await spacex.get("/launches");
setRockets(responseRocket.data);
setLaunches(responseLaunches.data);
};
fetchRockets().then(() => {
const mergedApis = () => {
const launchesCopy: any = [...launches];
for (let i = 0; i < launches.length; i++) {
for (let j = 0; j < rockets.length; j++) {
if (launches[i].rocket.rocket_name === rockets[j].rocket_name) {
launchesCopy[i].rocket = rockets[j];
}
}
}
setMerged(launchesCopy);
setIsLoading(false);
};
mergedApis();
});
}, []);
console.log(merged);
const handleSearchChange = (event: ChangeEvent<HTMLInputElement>) => {
setSearchTerm(event.target.value);
if (searchTerm.length === 0) {
setFilteredResult(merged);
} else if (searchTerm.length > 0) {
const filteredData = merged.filter((launch: Launch) => {
return `${launch.mission_name}`
.toLowerCase()
.includes(searchTerm.toLowerCase());
});
setFilteredResult(filteredData);
}
};
const lastPostIndex = currentPage * postsPerPage;
const firstPostIndex = lastPostIndex - postsPerPage;
const currentPosts = merged.slice(firstPostIndex, lastPostIndex);
return (
<>
<Header />
<div className="text-white">
<div>
<input
style={{
background:
"linear-gradient(0deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.05)), #121212",
}}
onChange={(event) => handleSearchChange(event)}
placeholder="Search all launches..."
value={searchTerm}
className="md:w-[26rem] w-[16rem] h-[3rem] rounded-lg mt-10 mx-5 md:mx-24 rounded-3"
/>
</div>
<div className="mx-5 md:ml-24 mt-5 opacity-40">
Total({currentPosts.length})
</div>
{isLoading ? (
<SkeletonGrid cards={postsPerPage} />
) : (
<CardGrid
postsData={currentPosts}
filteredResult={filteredResult}
searchTerm={searchTerm}
/>
)}
<Pagination
totalPosts={merged.length}
postsPerPage={postsPerPage}
setCurrentPage={setCurrentPage}
currentPage={currentPage}
/>
</div>
</>
);
};
export default LaunchesMain;
这是组件的代码。我该如何解决这个问题?
由于需要rockets
和launches
作为useEffect
的依赖项,因此无论何时它们发生变化,都会调用useEffect
,后者会调用api,后者会发生变化,等等。但是,除了合并它们之外,您不会使用rockets
和launches
状态,然后使用merged
状态。
因此,您不必在状态中存储rockets
和launches
。使用Promise.all()
将两个数据数组获取到.then()
块中,合并它们,并仅存储merged
状态:
useEffect(() => {
const fetchRockets = () => Promise.all(
spacex.get("/rockets"),
spacex.get("/launches")
])
fetchRockets()
.then(([responseRocket, responseLaunches]) => {
const rockets = responseRocket.data;
const launches = responseLaunches.data;
for (let i = 0; i < launches.length; i++) {
for (let j = 0; j < rockets.length; j++) {
if (launches[i].rocket.rocket_name === rockets[j].rocket_name) {
launches[i].rocket = rockets[j];
}
}
}
setMerged(launches);
setIsLoading(false);
});
}, []);