You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化该React+Firebase函数组件?解决重复渲染与点击更新异常

问题原因与修复方案

问题1:console.log("run!")执行1000次的原因

  • 核心触发逻辑:你在遍历1000条Firebase快照的forEach循环内,每次都调用setPopularMovies更新状态。React中每次状态更新都会触发组件重渲染,1000次状态更新对应1000次重渲染,组件顶层的console.log每次重渲染都会执行,自然就执行了1000次。
  • 修复逻辑:先将所有数据组装为完整数组,一次更新状态即可,避免循环内多次触发重渲染。

问题2:点击喜欢按钮隔一次才更新视图的原因

两个错误共同导致该现象:

  1. 更新render状态时用了后缀自增运算符render++:后缀自增会先返回变量的原始值,再给变量本身加1,因此setRender(render++)实际传给更新函数的是旧值,React判断状态无变化就不会触发重渲染。第二次点击时变量已经是自增后的值,才会触发一次更新,以此类推就出现了隔一次生效的现象。
  2. 你在likedMovie函数内直接修改普通变量index和movie:这些变量不属于React状态,修改后不会触发视图更新,只有组件重渲染时才会重新计算得到新的随机电影值。

额外优化:render状态完全多余,你不需要每次点击按钮都重新拉取全量1000条电影数据,初始拉取一次就足够后续随机取值使用。

修复后完整代码

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] = useState([]);
    // 新增随机触发器,替代原有无用的render状态,仅用于触发重渲染生成新随机电影
    const [randomTrigger, setRandomTrigger] = useState(false);

    console.log("run!");

    useEffect(() => {
        popularMoviesRef.once("value", function(snapshot){
            // 先组装完整数组,再一次更新状态,避免多次重渲染
            const movies = []
            snapshot.forEach(function(childSnapshot){
                const key = childSnapshot.key;
                const data = childSnapshot.val();
                movies.push({
                    key: key, 
                    movieTitle: data.movie_title, 
                    moviePoster: data.movie_poster, 
                    movieYear: data.movie_year,
                    movieGenre: data.movie_genre, 
                    movieRating: data.imdb_rating
                })
            })
            setPopularMovies(movies)
        });
    }, []); // 空依赖,初始仅拉取一次数据即可

    // 用数组长度替代写死的1000,避免数据不足时取到空值
    const index = Math.floor(Math.random() * popularMovies.length);
    const movie = popularMovies[index];

    const auth = firebase.auth();
    const db = firebase.firestore();
    const 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!");
            // 切换触发器状态,触发重渲染自动生成新的随机电影
            setRandomTrigger(prev => !prev);
        });
    }

    return (
        <div>
            <p>Rate Movies Here</p>
            <div> {movie?.movieTitle} </div>
            <div> {movie?.movieYear} </div>
            <br/>
            <button onClick={likedMovie}> Like</button>
            <button> Dislike</button>
            <br/>
            <br/>
            {/* React中class属性需写为className */}
            <img className="rate-image" src = {`${movie?.moviePoster}`} />
        </div>
    )
} 

export default RateMovies;

内容的提问来源于stack exchange,提问作者Kris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 17:15:03