从promise到async的重构等待并使用分页



我正在尝试重新考虑此代码以使用async/await

fetchTopRatedMovies(pageNumber).then((newData) =>
setApiData({
...newData,
results: [...apiData.results, ...newData.results]
})
);

I;我正试图在useEffect 中的try-catch块中使用它

这就是我到目前为止所拥有的。

useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(
`${baseURL}${option}?api_key=${API_KEY}&language=en&page=${pageNumber}&region=GB`
);
const data = await response.json();
setMovieData({
...movieData,
...data,
});
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
setLoading(true);
fetchData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [option, pageNumber]);

问题是我认为这部分是

const data = await response.json();
setMovieData({
...movieData,
...data,
});

作为我的状态const [movieData, setMovieData] = useState({ page: 0, results: [] });不是用旧数据更新,而是用页面上更改的新数据编号增加。

我的主要目标是有一个按钮,可以在已经显示的数据上添加更多的数据。

到目前为止的完整代码:


export const Directory = () => {
const [option, setOption] = useState('popular');
const [pageNumber, setPageNumber] = useState(1);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
const [movieData, setMovieData] = useState({ page: 0, results: [] });
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(
`${baseURL}${option}?api_key=${API_KEY}&language=en&page=${pageNumber}&region=GB`
);
const data = await response.json();
setMovieData({
...movieData,
...data,
});
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
setLoading(true);
fetchData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [option, pageNumber]);
const { results, page, total_pages } = movieData;
const handleOptionChange = e => {
setOption(e.target.value);
setPageNumber(1);
};
const pageLimit = page === 0 || page < total_pages;
return (
<div>
<select value={option} onChange={e => handleOptionChange(e)}>
<option value='popular'>Popular</option>
<option value='top_rated'>Top Rated</option>
<option value='now_playing'>Now Playing</option>
</select>
<ul>
{results &&
results.map(movie => {
return <li key={movie.id}>{movie.title}</li>;
})}
</ul>
{results && (
<button
disabled={!pageLimit}
onClick={() => setPageNumber(pageNumber + 1)}>
More
</button>
)}
</div>
);
};

目前一次只显示一个页面的结果数据。对于第一个渲染页面1也是如此。然后当我点击更多按钮时。它获取第2页的结果。但是,它一次只显示一页。我希望将新结果添加到已渲染的数据中。因此,每次按下按钮都会显示更多的结果。

data = await response.json()的console.log

{
"page": 1,
"total_results": 10000,
"total_pages": 500,
"results": [
{
"popularity": 728.376,
"vote_count": 3070,
"video": false,
"poster_path": "/xBHvZcjRiWyobQ9kxBhO6B2dtRI.jpg",
"id": 419704,
"adult": false,
"backdrop_path": "/5BwqwxMEjeFtdknRV792Svo0K1v.jpg",
"original_language": "en",
"original_title": "Ad Astra",
"genre_ids": [
18,
878
],
"title": "Ad Astra",
"vote_average": 6,
"overview": "The near future, a time when both hope and hardships drive humanity to look to the stars and beyond. While a mysterious phenomenon menaces to destroy life on planet Earth, astronaut Roy McBride undertakes a mission across the immensity of space and its many perils to uncover the truth about a lost expedition that decades before boldly faced emptiness and silence in search of the unknown.",
"release_date": "2019-09-18"
},
{
"popularity": 220.799,
"id": 454626,
"video": false,
"vote_count": 2868,
"vote_average": 7.5,
"title": "Sonic the Hedgehog",
"release_date": "2020-02-14",
"original_language": "en",
"original_title": "Sonic the Hedgehog",
"genre_ids": [
28,
878,
35,
10751
],
"backdrop_path": "/stmYfCUGd8Iy6kAMBr6AmWqx8Bq.jpg",
"adult": false,
"overview": "Based on the global blockbuster videogame franchise from Sega, Sonic the Hedgehog tells the story of the world’s speediest hedgehog as he embraces his new home on Earth. In this live-action adventure comedy, Sonic and his new best friend team up to defend the planet from the evil genius Dr. Robotnik and his plans for world domination.",
"poster_path": "/aQvJ5WPzZgYVDrxLX4R6cLJCEaQ.jpg"
},
{
"popularity": 204.235,
"vote_count": 3202,
"video": false,
"poster_path": "/y95lQLnuNKdPAzw9F9Ab8kJ80c3.jpg",
"id": 38700,
"adult": false,
"backdrop_path": "/upUy2QhMZEmtypPW3PdieKLAHxh.jpg",
"original_language": "en",
"original_title": "Bad Boys for Life",
"genre_ids": [
28,
80,
53
],
"title": "Bad Boys for Life",
"vote_average": 7.2,
"overview": "Marcus and Mike are forced to confront new threats, career changes, and midlife crises as they join the newly created elite team AMMO of the Miami police department to take down the ruthless Armando Armas, the vicious leader of a Miami drug cartel.",
"release_date": "2020-01-17"
}
]
}

您的movieData结构是:

{ page: 0, results: [] }

当你这样做:

setMovieData({
...movieData,
...data,
})

它只是用新的数据替换以前的数据。因为新数据和旧数据的密钥是相同的。你需要做的是这样的事情:

setMovieData({
results: [
...movieData.results, ...data.results
],
page: data.page
})

它将在旧数据之后追加新数据。希望能有所帮助。

另一个错误是以下代码:

const pageLimit = page === 0 || page < total_pages;

这需要使用movieData状态直接进行管理。更新您的代码如下:

return (
<div>
<select value={option} onChange={e => handleOptionChange(e)}>
<option value='popular'>Popular</option>
<option value='top_rated'>Top Rated</option>
<option value='now_playing'>Now Playing</option>
</select>
<ul>
{movieData.results &&
movieData.results.map(movie => {
return <li key={movie.id}>{movie.title}</li>;
})}
</ul>
{movieData.results && (
<button
disabled={!(movieData.page === 0 || movieData.page < total_pages)}
onClick={() => setPageNumber(pageNumber + 1)}>
More
</button>
)}
</div>
);

最新更新