首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >呈现此函数组件的更好方法是什么?

呈现此函数组件的更好方法是什么?
EN

Stack Overflow用户
提问于 2021-11-02 21:10:03
回答 1查看 49关注 0票数 1

以下代码的目标是将数据从firebase实时数据库拉入名为popularMovies的数组中。(实时数据库中的数据量为1000。)然后从该数组中选取一个随机索引,并在页面上显示该索引处的电影数据。当用户单击liked按钮时,该电影数据将存储在该用户id下的firestore文档中,并选择另一个随机索引来显示新电影。

下面的代码大部分都可以工作,但我注意到console.log("run!")在页面加载和单击liked按钮时执行1000次(正在读取的数据的大小)。我希望理解为什么会出现这种情况,因为它位于读取数据的forEach循环之外。

此外,当单击该按钮一次时,所有数据都会更新,但显示内容不会反映更改。但是,再次单击该按钮确实会随着显示再次更新数据(我预计第一次会发生这种情况)。并且这继续,按钮仅在每按下其他按钮之后更新显示。我还想知道是什么导致了这个bug。

代码语言:javascript
复制
import React, { useState, useEffect } from 'react';
import './App.css';
import firebase from 'firebase/compat/app';
import 'firebase/database';
import 'firebase/firestore';

function RateMovies() {

    const popularMoviesRef = firebase.database().ref("/popular_movies");
    const [popularMovies, setPopularMovies] = React.useState([]);
    var [render, setRender] = React.useState(1);

    console.log("run!");

    useEffect(() => {
        
        popularMoviesRef.once("value", function(snapshot){

            snapshot.forEach(function(childSnapshot){
                var key = childSnapshot.key;
                var data = childSnapshot.val();

                setPopularMovies(currMovies => [...currMovies, { 
                    key: key, 
                    movieTitle: data.movie_title, 
                    moviePoster: data.movie_poster, 
                    movieYear: data.movie_year,
                    movieGenre: data.movie_genre, 
                    movieRating: data.imdb_rating
                }])
            });
        });
    }, [render]);

    var index = Math.floor(Math.random() * (1000 + 1));
    var movie = popularMovies[index];

    const auth = firebase.auth();
    var db = firebase.firestore();
    var user_id = auth.currentUser.uid;

    function likedMovie() {

        db.collection('users').doc(user_id).update({
            "Rated.liked": firebase.firestore.FieldValue.arrayUnion({
                key: movie.key, 
                movieTitle: movie.movieTitle, 
                moviePoster: movie.moviePoster, 
                movieYear: movie.movieYear,
                movieGenre: movie.movieGenre, 
                movieRating: movie.movieRating,
             }),
        })
        .then(function(){
            console.log("Successfully updated!");
            setRender(render++);
        });

        index = Math.floor(Math.random() * (1000 + 1));
        movie = popularMovies[index];
    }


    return (
        <div>
            <p>Rate Movies Here</p>
            <div> {movie?.movieTitle} </div>
            <div> {movie?.movieYear} </div>
            <br/>
            <button onClick={likedMovie}> Like</button>
            <button> Disike</button>
            <br/>
            <br/>
            <img class="rate-image" src = {`${movie?.moviePoster}`} />
            
        </div>
    )
  
  } 

  export default RateMovies;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-02 21:15:49

之所以会看到1000次console.log(),是因为forEach()循环更新了RateMovies()中定义的状态变量(popularMovies)。每次状态改变时,React都会重新渲染你的组件。

不是一次添加一个新项,而是在forEach循环中创建一个新数组。这将只修改一次状态,这意味着组件应该只重新呈现一次。

尝试如下所示:

代码语言:javascript
复制
useEffect(() => {
        
        popularMoviesRef.once("value").then(function(snapshot){
            
            var newArray = []
    
            snapshot.forEach(function(childSnapshot){
                var key = childSnapshot.key;
                var data = childSnapshot.val();

                newArray.push({ 
                    key: key, 
                    movieTitle: data.movie_title, 
                    moviePoster: data.movie_poster, 
                    movieYear: data.movie_year,
                    movieGenre: data.movie_genre, 
                    movieRating: data.imdb_rating
                })
            });

            setPopularMovies([...popularMovies, ...newArray])

        }));
    }, [render]);

至于你的按钮没有重新渲染你想要的数据,我不能100%确定,但这可能与JavaScript处理promises的方式有关。useEffect中的popularMoviesRef.once调用可能与db.collection('users').doc(user_id).update同时发生。您可以通过将console.log()添加到useEffect函数来测试这一点,以尝试查看它是否在"Successfully Updated!"之前记录。

查看此处:What is the order of execution in JavaScript promises?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69816958

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档