尝试使用React Router useSearchParams对数据进行排序时尚未完成的React使用效果尚未完成
我有一个React组件,可以尝试先从TMDB API加载电影。然后,我创建一个使用查询参数对电影进行分类的按钮。我想使用查询参数,因为我想保留URL,以便我可以与排序值共享URL。 (这也是出于我的学习目的)。
当页面已经渲染并单击按钮时,它可以正常工作。
但是,当我尝试使用查询参数重新加载页面时,查询参数使用效果在电影完成之前先运行。
这是我的代码:
import { Box, Button } from '@mui/material';
import { useEffect, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import tmdb from '../apis/tmdb';
import MovieCard from '../components/MovieCard';
const MovieList = () => {
const [queryParams, setQueryParams] = useSearchParams();
const [movies, setMovies] = useState([]);
useEffect(() => {
const fetchMovies = async () => {
try {
const fetchedMovies = await tmdb.get("trending/movie/week");
setMovies(fetchedMovies.data.results);
} catch (error) {
console.log(error);
}
}
fetchMovies();
}, []);
useEffect(() => {
const sortMovies = (type) => {
if (type === 'asc') {
const sorted = movies.sort((a, b) => a.vote_average - b.vote_average);
setMovies(sorted);
}
if (type === 'desc') {
const sorted = movies.sort((a, b) => b.vote_average - a.vote_average);
setMovies(sorted);
}
}
sortMovies(queryParams.get('sort'));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [queryParams]);
const setSortParam = (type) => {
queryParams.set("sort", type);
setQueryParams(queryParams);
}
return (
<Box sx={{
display: 'flex',
flexDirection: 'column',
mt: 5,
}}>
<Box sx={{
mt: 5,
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
}}>
Sort by Rating
<Button
variant="contained"
sx={{ ml: 2 }}
onClick={() => setSortParam("asc")}
>
Asc
</Button>
<Button
variant="contained"
sx={{ ml: 2, mr: 2 }}
onClick={() => setSortParam("desc")}
>
Desc
</Button>
</Box>
<Box sx={{
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between',
}}>
{
movies.map(movie => (
<MovieCard key={movie.title} movie={movie}></MovieCard>
))
}
</Box>
</Box>
);
}
export default MovieList;
我尝试创建新状态以跟踪电影长度&gt; 0,但有时是越野车。我还尝试让USEREF跟踪电影长度&gt; 0但是它不起作用。
无论如何,是否可以等待首先使用效果完成?还是我应该使用其他方法来读取查询参数和排序?
I have a React component that try to load movies first from tmdb API. Then, I create a button to sort the movies using query params. I want to use query params because I want to preserve the URL so that I can share the URL with sort value. (This is for my learning purpose also).
When the page is already rendered and I click the button, it's work fine.
But when I try to reload the page with query params, the query params useEffect is run first before the movies finished loaded.
Here is my code:
import { Box, Button } from '@mui/material';
import { useEffect, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import tmdb from '../apis/tmdb';
import MovieCard from '../components/MovieCard';
const MovieList = () => {
const [queryParams, setQueryParams] = useSearchParams();
const [movies, setMovies] = useState([]);
useEffect(() => {
const fetchMovies = async () => {
try {
const fetchedMovies = await tmdb.get("trending/movie/week");
setMovies(fetchedMovies.data.results);
} catch (error) {
console.log(error);
}
}
fetchMovies();
}, []);
useEffect(() => {
const sortMovies = (type) => {
if (type === 'asc') {
const sorted = movies.sort((a, b) => a.vote_average - b.vote_average);
setMovies(sorted);
}
if (type === 'desc') {
const sorted = movies.sort((a, b) => b.vote_average - a.vote_average);
setMovies(sorted);
}
}
sortMovies(queryParams.get('sort'));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [queryParams]);
const setSortParam = (type) => {
queryParams.set("sort", type);
setQueryParams(queryParams);
}
return (
<Box sx={{
display: 'flex',
flexDirection: 'column',
mt: 5,
}}>
<Box sx={{
mt: 5,
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
}}>
Sort by Rating
<Button
variant="contained"
sx={{ ml: 2 }}
onClick={() => setSortParam("asc")}
>
Asc
</Button>
<Button
variant="contained"
sx={{ ml: 2, mr: 2 }}
onClick={() => setSortParam("desc")}
>
Desc
</Button>
</Box>
<Box sx={{
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between',
}}>
{
movies.map(movie => (
<MovieCard key={movie.title} movie={movie}></MovieCard>
))
}
</Box>
</Box>
);
}
export default MovieList;
I try to create new state to track if the movies length > 0, but sometimes it's buggy. I also try to useRef to track if the movies length > 0 but it's not working.
Is there anyway to wait for first useEffect to finish? Or should I use other approach than useEffect to read query params and sort?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为您正在尝试合并
电影
状态( ie真实)与派生状态( ie电影的排序顺序)) 。派生状态通常不属于状态。您可以轻松地从电影
状态和当前sort
querystring参数值中得出排序的电影
数组。示例:
如果需要,您可以使用
usememo
hook nock 值 hook nock nock,依赖于电影
状态>状态和当前sot
querystring参数值。例子:
I think you are trying to merge the
movies
state (i.e. the source of truth) with the derived state (i.e. the sorting order of movies). Derived state generally doesn't belong in state. You can easily derive the sortedmovies
array from themovies
state and the currentsort
queryString parameter value.Example:
If needed, you can memoize the
sortedMovies
value using theuseMemo
hook with a dependency on themovies
state and the currentsort
queryString parameter value.Example:
我认为您需要一个州来跟踪电影是否已加载
I think you need a state to track if the movies has been loaded