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> ); }
问题根源分析
首次请求404原因:
React状态更新是异步的,handleSubmit中调用setanilistURL后立刻在finally执行getReviews,此时anilistURL还是初始空值,拼接出的评论URL为"/reviews",导致请求地址错误。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
相关产品推荐
相关产品推荐

