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

React中forEach计算正常但内容不显示问题求助

问题分析与解决方案

看起来你遇到的核心问题是没有用React State来追踪挑战列表的变化,导致数据更新后组件没有重新渲染,所以页面上看不到挑战名称。让我一步步帮你解决这个问题:

核心问题拆解

  1. 你用了普通变量size来存储挑战列表,但React不会监听普通变量的变化——只有当组件的state或props更新时,React才会重新渲染组件。所以即使你在fetchData里更新了size,组件也不会知道,自然不会展示新的内容。
  2. allowProgressBar里调用createMultipleProgressBars()只是执行了函数,但没有把返回的JSX和组件的渲染生命周期绑定起来,所以这个函数的返回值并没有被用来更新页面。

具体修复步骤

1. 将挑战列表改为React State

把原来的var size = []替换为state变量,让React能追踪它的变化:

const [challenges, setChallenges] = useState([]);

2. 更新数据获取逻辑

在fetchData里,获取到挑战列表后,用setChallenges来更新state,而不是直接赋值给普通变量:

useEffect(() => {
  const fetchData = async () => {
    if (!user) return; // 先判断用户是否存在,避免报错
    const challs = [];
    const snapshot = await database
      .collection("Users")
      .doc(email)
      .collection("ChosenChallenge")
      .get();
    snapshot.docs.forEach((doc) => {
      challs.push(doc.data().chall);
    });
    setChallenges(challs); // 用state更新函数替换直接赋值
  };
  fetchData();
}, [user, email]); // 添加依赖,确保用户信息变化时重新获取数据

3. 简化渲染逻辑

不需要showProgressBar这个state了,直接根据challenges的长度判断是否展示挑战列表。同时重构渲染逻辑,让它更简洁:

const renderProgressBar = () => {
  if (challenges.length === 0) {
    return (
      <p> Oh no! You have not committed to any challenges yet. Click on the + sign in the bottom to begin </p>
    );
  }
  // 直接渲染挑战列表,不需要单独的createMultipleProgressBars函数
  return (
    <div>
      {challenges.map((challenge) => (
        <div key={challenge}>
          <p>{challenge}</p>
        </div>
      ))}
    </div>
  );
};

4. 修复用户信息的依赖问题

原来的user和email是直接从firebase.auth().currentUser获取的,初始可能为null,所以需要把用户信息也改成state并监听登录状态:

// 添加用户state,追踪登录状态变化
const [user, setUser] = useState(firebase.auth().currentUser);

useEffect(() => {
  // 监听用户登录状态变化
  const unsubscribe = firebase.auth().onAuthStateChanged((currentUser) => {
    setUser(currentUser);
  });
  return unsubscribe; // 清理订阅
}, []);

// 推导email,可选链避免空值报错
const email = user?.email;

修改后的完整Dashboard组件代码

import React, { useState, useEffect } from "react";
import "./Dashboard.css";
import leafpic from "./img/leaf.png";
import Co2 from './Co2';
import Header from "./Header";
import { database } from "../firebase";
import firebase from "firebase/app";

export default function Dashboard() {
  // 用state管理用户和挑战列表
  const [user, setUser] = useState(firebase.auth().currentUser);
  const [challenges, setChallenges] = useState([]);
  const email = user?.email;

  // 监听用户登录状态变化
  useEffect(() => {
    const unsubscribe = firebase.auth().onAuthStateChanged((currentUser) => {
      setUser(currentUser);
    });
    return unsubscribe;
  }, []);

  // 获取用户选择的挑战
  useEffect(() => {
    if (!email) return;

    const fetchData = async () => {
      const challs = [];
      const snapshot = await database
        .collection("Users")
        .doc(email)
        .collection("ChosenChallenge")
        .get();
      snapshot.docs.forEach((doc) => {
        challs.push(doc.data().chall);
      });
      setChallenges(challs);
    };

    fetchData();
  }, [email]);

  // 设置用户基本信息
  useEffect(() => {
    if (!user) return;

    database
      .collection("Users")
      .doc(email)
      .set({
        name: user.displayName,
        co2: 0
      }, { merge: true }) // 用merge避免覆盖已有数据
      .then(() => {
        console.log("user info updated!");
      });
  }, [user, email]);

  const renderProgressBar = () => {
    if (challenges.length === 0) {
      return (
        <p> Oh no! You have not committed to any challenges yet. Click on the + sign in the bottom to begin </p>
      );
    }

    return (
      <div>
        {challenges.map((challenge) => (
          <div key={challenge}>
            <p>{challenge}</p>
          </div>
        ))}
      </div>
    );
  };

  return (
    <div className="Dashboard">
      <Header />
      <div className="circle">
        <img id="leafpicture" src={leafpic} alt="eco-picture" />
        <div className="textIn">
          <h1> You saved </h1>
          <h5><Co2 user={email} />kg CO2</h5>
        </div>
      </div>
      <div className="progressbar">
        <h3>Track your challenges!</h3>
        <div>
          {renderProgressBar()}
        </div>
      </div>
      <br />
      <br />
    </div>
  );
}

额外优化点

  • 在set用户信息时添加了{ merge: true },避免覆盖用户文档里已有的其他数据(比如后续更新的co2值)。
  • 添加了用户登录状态的监听,确保用户信息变化时组件能及时更新。
  • 去掉了重复的样式导入和未使用的组件导入,精简代码。

这样修改后,当你的挑战列表获取到数据并更新state时,React会自动重新渲染组件,页面上就能正常显示挑战名称了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:06:13