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

ReactJS中reviewTitles数组状态变更未同步至UI的问题求助

React组件中reviewTitles无法显示的问题修复

问题概述

核心问题是reviewTitles状态更新后无法在UI渲染,同时伴随以下现象:

  • 首次点击「Analyze」按钮,Anilist URL正常显示,但获取评论标题的请求报404错误
  • 二次点击按钮,Anilist URL正常显示,loadingReviews对应的加载提示出现,但评论标题仍不显示

原组件代码

import React, { useState } from "react";

export default function Recommend() {
  const [animeName, setAnimeName] = useState("");
  const [anilistURL, setanilistURL] = useState("");
  const [errorMsg, setErrorMsg] = useState("");
  const [loading, setLoading] = useState(false);
  const [loadingReviews, setLoadingReviews] = useState(false);
  const [reviewTitles, setreviewTitles] = useState([]);

  const handleSubmit = async () => {
    try {
      setLoading(true);
      setreviewTitles([]);
      setanilistURL("");
      setErrorMsg("");

      const response = await fetch("http://localhost:8000/get-anilist-url", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          anime_title: animeName,
        }),
      });
      if (!response.ok) {
        const errorData = await response.json();
        setErrorMsg(errorData.error || "Unable to get response");
      }
      const data = await response.json();
      setanilistURL(data.anilist_url || "No URL found");
      setErrorMsg("");
    } catch (error) {
      setErrorMsg("An error occurred: " + error.message);
    } finally {
      setLoading(false);
      getReviews();
    }
  };

  const getReviews = async () => {
    try {
      setLoadingReviews(true);
      setErrorMsg("");
      const anilistReviewsURL = anilistURL + "/reviews";
      const response = await fetch(
        "http://localhost:3000/api/v1/scrape/get-review-titles",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ reviewsLink: anilistReviewsURL }),
        }
      );
      const data = await response.json();
      if (!response.ok) {
        setErrorMsg(data.error || "Unable to get response");
      }
      setreviewTitles((prevTitles) => [
        ...prevTitles,
        data.reviewTitles
      ]);
      setErrorMsg("");

    } catch (error) {
      setErrorMsg("An error occurred: " + error);
    }
    finally {
      setLoadingReviews(false);
    }
  };

  return (
    <div className="flex flex-col h-screen bg-slate-700">
      <div className="flex-grow bg-slate-600 p-5 font-mono">
        {loading && <div className="text-white">Loading...</div>}
        {errorMsg && <div className="text-red-500">{errorMsg}</div>}
        {anilistURL && (
          <div className="text-yellow-100">
            <p>Anilist URL:</p>
            <a href={anilistURL} target="_blank" rel="noopener noreferrer">
              {anilistURL}
            </a>
          </div>
        )}
        {loadingReviews && <div className="text-white">Loading...</div>}
        {reviewTitles && (
          reviewTitles.map((reviewTitle) => {
            (
              <div className = "text-yellow-500 pt-3">
                {reviewTitle}
              </div>
            )
          })
        )}
      </div>
      <div className="p-4 flex items-center justify-between bg-slate-800">
        <h3 className="text-gray-500 text-3xl font-mono">
          Enter anime to be analyzed
        </h3>
        <textarea
          type="text"
          className="bg-slate-700 font-mono text-white text-2xl p-3 border-none outline-none w-full rounded-full"
          placeholder="Enter your prompt..."
          value={animeName}
          onChange={(e) => setAnimeName(e.target.value)}
        />
        <button
          className="bg-slate-700 font-mono text-white text-2xl p-4 rounded-full hover:bg-slate-600 transition duration-200 ml-5"
          onClick={handleSubmit}
        >
          Analyze
        </button>
      </div>
    </div>
  );
}

问题根源分析

  1. 首次请求404原因:
    React状态更新是异步的,handleSubmit中调用setanilistURL后立刻在finally执行getReviews,此时anilistURL还是初始空值,拼接出的评论URL为"/reviews",导致请求地址错误。

  2. reviewTitles不渲染原因:

    • 状态更新错误:把data.reviewTitles(数组)直接作为元素添加到原数组,使reviewTitles变成二维数组,map遍历后无法渲染内容
    • map函数无返回值:当前map内的JSX未被return,React无法识别要渲染的元素
    • 错误处理漏洞:请求返回不ok时未终止后续代码,仍会执行状态更新,可能覆盖错误信息

修复方案

1. 修正getReviews调用时机

直接传递获取到的URL参数,避免依赖异步更新的状态:

const handleSubmit = async () => {
  try {
    setLoading(true);
    setreviewTitles([]);
    setanilistURL("");
    setErrorMsg("");

    const response = await fetch("http://localhost:8000/get-anilist-url", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        anime_title: animeName,
      }),
    });
    if (!response.ok) {
      const errorData = await response.json();
      setErrorMsg(errorData.error || "Unable to get response");
      return; // 错误时终止后续执行
    }
    const data = await response.json();
    const url = data.anilist_url || "No URL found";
    setanilistURL(url);
    setErrorMsg("");
    await getReviews(url); // 直接传入最新URL
  } catch (error) {
    setErrorMsg("An error occurred: " + error.message);
  } finally {
    setLoading(false);
  }
};

2. 修正getReviews函数

接收URL参数,修复状态更新逻辑:

const getReviews = async (url) => {
  try {
    setLoadingReviews(true);
    setErrorMsg("");
    const anilistReviewsURL = url + "/reviews";
    const response = await fetch(
      "http://localhost:3000/api/v1/scrape/get-review-titles",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ reviewsLink: anilistReviewsURL }),
      }
    );
    if (!response.ok) {
      const errorData = await response.json();
      setErrorMsg(errorData.error || "Unable to get response");
      return;
    }
    const data = await response.json();
    setreviewTitles(data.reviewTitles); // 直接赋值数组,而非嵌套添加
    setErrorMsg("");

  } catch (error) {
    setErrorMsg("An error occurred: " + error.message);
  } finally {
    setLoadingReviews(false);
  }
};

3. 修正UI渲染的map逻辑

确保map返回JSX元素,添加key属性并处理空数组场景:

{reviewTitles.length > 0 ? (
  reviewTitles.map((reviewTitle, index) => (
    <div key={index} className="text-yellow-500 pt-3">
      {reviewTitle}
    </div>
  ))
) : (
  !loadingReviews && <div className="text-white">暂无评论标题</div>
)}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 04:10:08