反应元素不显示

React elements not showing

这可能已经被问过无数次了,我已经查看了一百个不同的地方并尝试了 100 种不同的方法,其中有或多或少的 useEffects 和 returns,但我就是做不到修复它!

我正在尝试显示电影列表中的内容,但无法显示。 我可以在日志中看到我在第二个 useEffect 的“电影”中确实有我需要的东西,但它不产生任何元素,我只得到包装 div.

我的密码:

const SideScroller = ({scrollerName, titles}) => {
    const [movies, setMovies] = useState([]);
    const [content, setContent] = useState();

    useEffect(() => {
        let moviesTemp = [];
        
        titles.forEach(title => {
            async function fetchData() {
                const movie = await getMovie(title);
                moviesTemp.push(movie);
            }
            fetchData();
        });
        setMovies(moviesTemp);
    }, [titles])
   
    useEffect(() => {
        console.log(movies)
        setContent(() => {
            return (
                movies.map((movie) => {
                    console.log(movie);
                    return (
                        <div className='scrollerItem'>
                            <img src={movie.Poster} alt={movie.Title}  />
                            <p>{movie.Title}</p>
                        </div>
                    );
                })
            );
        });
    }, [movies])

    return (
        <div className='sideScroller'>
            {content}
        </div>
    )
}

Try Like This

setContent(() => {
movies.map((movie) => {
console.log(movie);
return (
<div className='scrollerItem'>
<img src={movie.Poster} alt={movie.Title}  />
<p>{movie.Title}</p>
</div>
);
})
});

您正在将 forEach 的承诺丢在地板上,而不是等待它。这其实和大名鼎鼎的How do I return the response from an asynchronous call?

一样
    useEffect(() => {
        let moviesTemp = [];
        
        const fetch = async () => {
         await Promise.all(titles.map(title => {
            async function fetchData() {
                const movie = await getMovie(title);
                moviesTemp.push(movie);
            }
            return fetchData();
         }));
         setMovies(moviesTemp);
        }
        fetch();
    }, [titles])

然后为了好玩我重写了一点(不是因为它一定比其他方式“更好”):

    useEffect(() => {
        const moviesTemp = [];
        const fetch = async (title) => moviesTemp.push(await getMovie(title))
        const fetchAll = async () => {
          await Promise.all(titles.map(fetch)); 
          setMovies(moviesTemp);
        }
        fetchAll();
    }, [titles])

编辑:为了解决你的第二个问题(在评论中),这是因为你改变了状态。

这是一件非常奇怪的事情,但让我试着解释一下:

    useEffect(() => {
        let moviesTemp = [];
        
        titles.forEach(title => {
            async function fetchData() {
                const movie = await getMovie(title);
                moviesTemp.push(movie);
            }
            fetchData();
        });
        setMovies(moviesTemp);
    }, [titles])

你立即(因为 forEach 是同步的,不管它在每次迭代中执行异步函数这一事实)将新状态设置为 moviesTemp,但是随后,你异步修改了 moviesTemp 这与变异状态完全相同。如果你在反应中改变东西,它不起作用。

另外,你不应该有第二个效果,这就是你的完整和最终组件应该是这样的:

const SideScroller = ({scrollerName, titles}) => {
    const [movies, setMovies] = useState([]);

    useEffect(() => {
        const fetchAll = async () => setMovies(
          await Promise.all(titles.map(getMovie))
        );
        fetchAll();
    }, [titles])


    return (
        <div className='sideScroller'>
           {movies.map((movie) => {
                    return (
                        <div className='scrollerItem'>
                            <img src={movie.Poster} alt={movie.Title}  />
                            <p>{movie.Title}</p>
                        </div>
                    );
                })
            }
        </div>
    )
}

试试这个:

const SideScroller = ({scrollerName, titles}) => {
    const [movies, setMovies] = useState([]);

    useEffect(() => {
        async function fetchData() {
            let moviesTemp = [];
            for (const title of titles) {
                const movie = await getMovie(title);
                moviesTemp.push(movie);
            }
            setMovies(moviesTemp);
        };
        fetchData();
    }, [titles])
   
    return (
        <div className='sideScroller'>
            {movies.map((movie) => {
                    console.log(movie);
                    return (
                        <div className='scrollerItem'>
                            <img src={movie.Poster} alt={movie.Title}  />
                            <p>{movie.Title}</p>
                        </div>
                    );
                })}
        </div>
    )
}