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

React刷新页面后子组件props变为undefined的解决方法

问题根因

报错props.response.names.length为undefined由3个核心代码错误导致:

  • 状态初始化逻辑错误:useState(makeRequest)会触发React的惰性初始化机制,直接执行传入的makeRequest异步函数拿返回值作为初始状态。异步函数永远返回Promise对象,完全不匹配接口返回的JSON结构,初始状态下根本不存在names字段。
  • 状态更新逻辑错误:useEffect中写setResponse(makeRequest)时,既没有给makeRequest加调用括号,也没有取到接口返回数据——makeRequest本身是函数引用,直接传给setResponse会把response的值设为函数对象,完全覆盖掉makeRequest内部调用setResponse(json)设置的正确接口数据。
  • 子组件无空值兜底:API请求是异步行为,组件首次渲染时请求还未返回,此时直接访问深层属性props.response.names.length必然触发报错。

另外还有两个小问题会导致编译异常:App.js中使用了logo变量但未导入,Tags.js中错误导入了父组件App.js。

修正方案

1. 修复App.js的状态与请求逻辑

  • 将response初始值设为null,和后续接口返回的结构做兼容
  • 把请求逻辑直接放到useEffect中执行,请求成功后再调用setResponse存入解析后的JSON数据
  • 补上缺失的logo导入,移除无效外链
import './App.css';
import Tags from './Tags.js';
import React, { useState, useEffect } from 'react';
import logo from './logo.svg'; // 按项目实际路径调整导入地址

function App() {
  const [response, setResponse] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const makeRequest = async () => {
      try {
        let res = await fetch('RANDOM_API_URL');
        let json = await res.json();
        setResponse(json);
      } catch (error) {
        console.log(error);
      } finally {
        setLoading(false);
      }
    }
    makeRequest();
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="#"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
      {loading ? <p>数据加载中...</p> : <Tags response={response}></Tags>}
    </div>
  );
}

export default App;

2. 修复Tags.js的空值判断与无效导入

  • 删除错误的父组件导入语句
  • 访问response的深层属性前做空值兜底,避免请求未完成时触发报错
function Tags(props) {
  // 兜底处理:属性不存在时默认返回空数组
  const nameList = props?.response?.names || [];
  
  const makeButtons = () => {
    let result = [];
    for (let i = 0; i < nameList.length; i++) {
      result.push(<button key={i}>{nameList[i] || 'hello'}</button>);
    }
    return result;
  }

  return (
    <div>
      {makeButtons()}
    </div>
  );
}

export default Tags;
关键注意点
  • 所有异步请求返回的数据,在组件首次渲染阶段一定是未就绪的,必须给初始状态设置匹配接口结构的默认值,或者在子组件访问属性前做空值判断
  • useState传入函数作为参数时,React会在初始化阶段直接执行该函数,拿同步返回值作为初始状态,不要直接把异步请求函数传给useState
  • setState只接收最终要存储的状态值,不要把函数引用、Promise对象直接传给setState

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 19:36:33