React组件获取JSON数据后渲染时值为undefined的问题求助
问题解决:异步请求导致返回值未更新
问题描述
尝试从接口获取电影数据并存入details对象返回,在GetMovieDetails函数内部的回调中能通过console.log看到正确数值,但父组件中打印该对象时所有属性全为undefined,无法用这些值渲染组件。
原代码
import React from "react" import theMovieDb from './moviedb.js' export default function MovieDetails(props){ const movieDetails = GetMovieDetails(props.id) console.log(movieDetails) function GetMovieDetails(id) { var details = { genres: undefined, title: undefined, imdbID: undefined, popularity: undefined, releaseDate: undefined, posterPath: undefined, } theMovieDb.movies.getById({ "id" : id }, function( data ) { data = JSON.parse( data ); details.genres = data.genres details.title = data.original_title details.imdbID = data.imdb_id details.popularity = data.popularity details.releaseDate = data.poster_path // 赋值错误 details.posterPath = data.release_date // 赋值错误 console.log(details) }, function( err ) { console.error(err) }); return details; } return ( <div className='movie-card-container'> <div > <h1>Title: {movieDetails.title}</h1> <h2>Year Released: 2005 </h2> <h2>Genre: Action/Sci-Fi</h2> <h3>Run Time: 2h 20m</h3> </div> </div> ); }
问题原因
- 异步时序问题:
theMovieDb.movies.getById是异步HTTP请求,回调函数要等请求成功后才执行,但GetMovieDetails会立即同步返回初始的details对象,此时所有属性都是undefined。等回调里修改details时,组件已经完成第一次渲染,且没有触发重渲染的机制,页面无法更新数据。 - 状态管理缺失:用普通变量存储异步数据,React无法感知变量变化,不会触发组件重渲染。
解决方案
使用React的useState管理状态,useEffect触发异步请求,确保数据更新后组件自动重渲染:
import React, { useState, useEffect } from "react" import theMovieDb from './moviedb.js' export default function MovieDetails(props){ // 初始化电影详情状态 const [movieDetails, setMovieDetails] = useState({ genres: [], title: "", imdbID: "", popularity: 0, releaseDate: "", posterPath: "", }); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { function fetchMovieDetails() { theMovieDb.movies.getById({ "id" : props.id }, function( data ) { const parsedData = JSON.parse(data); // 修正赋值错误,组装正确的详情对象 const details = { genres: parsedData.genres, title: parsedData.original_title, imdbID: parsedData.imdb_id, popularity: parsedData.popularity, releaseDate: parsedData.release_date, posterPath: parsedData.poster_path, }; setMovieDetails(details); setLoading(false); }, function( err ) { setError(err); setLoading(false); console.error(err); }); } fetchMovieDetails(); }, [props.id]); // 依赖props.id,ID变化时重新请求 // 加载状态处理 if (loading) return <div>加载中...</div>; // 错误状态处理 if (error) return <div>加载失败:{error.message}</div>; return ( <div className='movie-card-container'> <div > <h1>Title: {movieDetails.title}</h1> <h2>Year Released: {movieDetails.releaseDate.split('-')[0]}</h2> <h2>Genre: {movieDetails.genres.map(g => g.name).join("/")}</h2> <h3>Popularity: {movieDetails.popularity.toFixed(1)}</h3> </div> </div> ); }
关键修改点
- 用
useState定义movieDetails状态,让React能追踪数据变化并触发重渲染。 - 用
useEffect在组件挂载或props.id变化时触发异步请求,避免无效重复请求。 - 修正了原代码中
releaseDate和posterPath的赋值错误。 - 添加加载、错误状态处理,提升页面交互体验。
内容的提问来源于stack exchange,提问作者Tom Hartley
相关产品推荐
相关产品推荐

