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

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>
    );
}

问题原因

  1. 异步时序问题:theMovieDb.movies.getById是异步HTTP请求,回调函数要等请求成功后才执行,但GetMovieDetails会立即同步返回初始的details对象,此时所有属性都是undefined。等回调里修改details时,组件已经完成第一次渲染,且没有触发重渲染的机制,页面无法更新数据。
  2. 状态管理缺失:用普通变量存储异步数据,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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 03:50:48