React组件状态更新但未重新渲染问题求助
React组件渲染异常问题解决
问题场景
在GameComponent中,通过useEffect调用API获取captions并更新状态后,API请求成功(AnswerContainer的console.log能正常打印返回的captions数据),但Answer组件既不渲染内容,也没有执行内部的console.log输出。
原始代码
import { Row,Col,Navbar,Button,Form,Card,Image,Table,Container, Stack} from "react-bootstrap"; import {Link, useNavigate,useParams} from "react-router-dom" import {React, useState,useEffect} from 'react'; import './GameComponents.css' import API from "../API.mjs"; //ignore this component function Timer(){ const [seconds,setSeconds]= useState(30); const [percentage, setPercentage] = useState(100); useEffect(() => { if (seconds > 0) { const timerId = setTimeout(() => { setSeconds(seconds - 1); setPercentage((seconds - 1) / 30 * 100); // Calculate percentage }, 1000); return () => clearTimeout(timerId); // clean timeout } }, [seconds]); return( <Card> <Card.Body> <div> <h1 className="TimerTitle">Timer: {seconds} seconds</h1> <div className="progress-bar"> <div className="progress-bar-fill" style={{ width: `${percentage}%` }} ></div> </div> </div> </Card.Body> </Card> ); } //ignore this component function ImageContainer(props){ //console.log(props.memes); return( <Image className="image-container image-border" src='./src/images/tradeoffer.jpg' rounded/> ); } //console.log is not printed the first time, then it is printed function AnswersContainer(props){ console.log(props.captions) return(<> <Stack gap={5} className="CaptionComponent"> {props.captions.map((caption)=>{ <Row><Answer caption={caption}/></Row> })} </Stack> </>) } //this console.log() is never printed function Answer(props){ console.log("inside answer") return( <Row> <Button variant="light">{props.caption}</Button> </Row> ); } function GameComponent(){ const [memes,setMemes]= useState([]); const [captions,setCaptions]= useState([]); //useEffect to set memes state useEffect(()=>{ const getMeme=async ()=>{ const m=await API.getMemes(); setMemes(m); } getMeme(); },[]); //useEffect to set captions state useEffect(()=>{ const getCaption=async ()=>{ const c=await API.getCaptions(); setCaptions(c); } getCaption(); },[]); return(<> <Container className="MainContainer"> <Card> <Row> <Timer/> </Row> <Row> <Col md={6}> <ImageContainer memes={memes}/> </Col> <Col md={6}> <AnswersContainer captions={captions}/> </Col> </Row> </Card> </Container> </>); } export default GameComponent;
问题原因
核心问题在AnswersContainer的map函数中:没有返回生成的JSX元素。map函数需要明确返回要渲染的元素,否则不会生成任何组件,导致Answer组件从未被实例化,自然不会执行内部代码或渲染内容。
另外,React要求列表渲染的元素必须带有唯一的key属性,这也是需要补充的规范点。
修复方案
修改AnswersContainer组件,在map函数中返回JSX元素,并添加key属性:
function AnswersContainer(props){ console.log(props.captions) return(<> <Stack gap={5} className="CaptionComponent"> {props.captions.map((caption, index) => { // 1. 显式返回JSX元素 // 2. 添加唯一key(建议用caption的唯一ID,这里先用index临时替代) return <Row key={index}><Answer caption={caption}/></Row> })} </Stack> </>) }
简化写法(可选)
可以用箭头函数的隐式返回简化代码:
function AnswersContainer(props){ console.log(props.captions) return(<> <Stack gap={5} className="CaptionComponent"> {props.captions.map((caption, index) => ( <Row key={index}><Answer caption={caption}/></Row> ))} </Stack> </>) }
修改后,Answer组件会正常渲染,内部的console.log也会执行。
内容的提问来源于stack exchange,提问作者Giovanni Giordano
相关产品推荐
相关产品推荐

