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

React页面刷新因数据未加载崩溃,除&&运算符外有更佳方案吗?

解决React中API数据加载前的页面崩溃问题

在测试API调用的沙箱项目时,页面刷新会崩溃,原因是页面加载速度快于数据获取速度。用逻辑与(&&)运算符添加检查能修复问题,但还有几种更实用的替代方案:

崩溃的原始代码

import React, { useEffect, useState } from "react";
import { Heading } from "./components/Heading";

const URL = "https://api.sleeper.app/v1/league/867824542855376896";

function App() {
  const [data, setData] = useState(null);

  const getData = async () => {
    try {
      const res = await fetch(URL);
      const data = await res.json();
      setData(data);
    } catch (err) {
      console.log(err);
    }
  };

  useEffect(() => {
    getData();
  }, []);

  console.log(data);
  return (
    <>
      <Heading str="Hello world" />
      <Heading str="Hello friend" />
      <h1>{data.bracket_id}</h1>
      {data.roster_positions.map((pos, i) => {
          return <h1 key={i + 1}>{pos}</h1>;
        })}
    </>
  );
}

export default App;

修复后的代码(使用&&)

import React, { useEffect, useState } from "react";
import { Heading } from "./components/Heading";

const URL = "https://api.sleeper.app/v1/league/867824542855376896";

function App() {
  const [data, setData] = useState(null);

  const getData = async () => {
    try {
      const res = await fetch(URL);
      const data = await res.json();
      setData(data);
    } catch (err) {
      console.log(err);
    }
  };

  useEffect(() => {
    getData();
  }, []);

  console.log(data);
  return (
    <>
      <Heading str="Hello world" />
      <Heading str="Hello friend" />
      <h1>{data && data.bracket_id}</h1>
      {data &&
        data.roster_positions.map((pos, i) => {
          return <h1 key={i + 1}>{pos}</h1>;
        })}
    </>
  );
}

export default App;

更优替代方案

1. 初始化状态为匹配数据结构的空值

将useState的初始值从null改为和API返回数据结构一致的空值,这样即使数据未加载完成,访问属性或调用map也不会报错:

// 初始值匹配API返回的结构
const [data, setData] = useState({ bracket_id: '', roster_positions: [] });

这种方法无需额外的条件判断,代码更简洁,适合数据结构固定的场景。

2. 使用可选链操作符(?.)替代逻辑与

ES2020引入的可选链操作符可以更简洁地处理空值判断,当左侧值为null或undefined时,会直接返回undefined,不会继续访问后续属性:

<h1>{data?.bracket_id}</h1>
{data?.roster_positions?.map((pos, i) => {
  return <h1 key={i + 1}>{pos}</h1>;
})}

相比&&,可选链在处理多层嵌套的属性时更清晰,避免了data && data.user && data.user.name这类冗长写法。

3. 添加加载状态,渲染加载提示

如果要提升用户体验,可以增加一个加载状态,在数据未就绪时显示加载提示,完全避免未定义数据的渲染:

import React, { useEffect, useState } from "react";
import { Heading } from "./components/Heading";

const URL = "https://api.sleeper.app/v1/league/867824542855376896";

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

  const getData = async () => {
    try {
      const res = await fetch(URL);
      const data = await res.json();
      setData(data);
    } catch (err) {
      console.log(err);
    } finally {
      setLoading(false); // 无论请求成功或失败,都结束加载状态
    }
  };

  useEffect(() => {
    getData();
  }, []);

  // 加载中时显示提示
  if (loading) {
    return <div>加载中...</div>;
  }

  return (
    <>
      <Heading str="Hello world" />
      <Heading str="Hello friend" />
      <h1>{data.bracket_id}</h1>
      {data.roster_positions.map((pos, i) => {
        return <h1 key={i + 1}>{pos}</h1>;
      })}
    </>
  );
}

export default App;

这种方式不仅解决了崩溃问题,还能让用户明确知道页面的加载状态,提升交互体验。

4. 使用错误边界捕获渲染异常

对于更复杂的应用,可以创建错误边界组件,用来捕获子组件渲染时的异常,并显示备用UI。错误边界是React提供的全局处理渲染错误的机制,适合需要统一处理异常场景的项目。

总结

你使用&&的做法是有效的,但上述方案各有优势:初始化匹配结构适合简单场景,可选链写法更简洁,加载状态提升用户体验,错误边界适合全局异常处理。可以根据项目的复杂度和需求选择合适的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 03:07:24