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

React/Next.js组件提前加载数据问题:如何等待getArticles()后渲染UI?

在React/Next.js中等待数据加载完成后渲染UI的解决方案

一、通用React场景:利用状态管理的加载状态

既然使用了useDispatch,说明项目大概率基于Redux(或类似状态管理库)。核心思路是给blog状态新增加载状态(loading)和错误状态(error),通过追踪这些状态控制UI渲染逻辑:

1. 完善Action逻辑,添加加载状态标记

在获取文章的Action中,分三个阶段更新状态:请求发起时标记加载中,请求成功后更新数据并结束加载,请求失败时记录错误并结束加载:

// actions/blogActions.js
export const getArticles = () => async (dispatch) => {
  // 标记加载开始
  dispatch({ type: 'GET_ARTICLES_LOADING' });
  try {
    const res = await fetch('/api/articles');
    const articles = await res.json();
    // 请求成功,更新文章数据
    dispatch({ type: 'GET_ARTICLES_SUCCESS', payload: articles });
  } catch (err) {
    // 请求失败,记录错误信息
    dispatch({ type: 'GET_ARTICLES_FAILURE', payload: err.message });
  }
};

2. 更新Reducer维护状态

在Reducer中处理上述Action,维护loading、articles、error三个核心状态:

// reducers/blogReducer.js
const initialState = {
  articles: [],
  loading: false,
  error: null
};

export default function blogReducer(state = initialState, action) {
  switch (action.type) {
    case 'GET_ARTICLES_LOADING':
      return { ...state, loading: true, error: null };
    case 'GET_ARTICLES_SUCCESS':
      return { ...state, loading: false, articles: action.payload };
    case 'GET_ARTICLES_FAILURE':
      return { ...state, loading: false, error: action.payload };
    default:
      return state;
  }
}

3. 组件中根据状态渲染UI

在组件中读取loading、articles、error状态,分别渲染加载提示、文章列表、错误信息:

import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getArticles } from '../actions/blogActions';

function Blog() {
  const dispatch = useDispatch();
  const { articles, loading, error } = useSelector(state => state.blog);

  useEffect(() => {
    dispatch(getArticles());
  }, [dispatch]);

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

  // 加载失败时显示错误信息
  if (error) {
    return <div>加载失败:{error}</div>;
  }

  // 数据就绪后渲染文章列表
  return (
    <div>
      {articles.map((item) => (
        <div key={item.id}>{item.name}</div>
      ))}
    </div>
  );
}

export default Blog;

二、Next.js专属方案:预渲染数据获取

Next.js提供三种预渲染数据获取方式,能在组件渲染前就拿到数据,彻底避免客户端useEffect带来的延迟:

1. 静态生成(SSG)- getStaticProps

适合数据不频繁更新的场景,构建时一次性获取数据生成静态页面,性能最优:

// pages/blog.js
// 该函数在构建时执行(服务器端)
export async function getStaticProps() {
  const res = await fetch('https://你的API地址/articles');
  const articles = await res.json();

  return {
    props: { articles }, // 将数据作为props传递给组件
    revalidate: 60, // 可选:每隔60秒重新生成页面(增量静态再生)
  };
}

// 组件直接接收预获取的articles
function Blog({ articles }) {
  return (
    <div>
      {articles.map((item) => (
        <div key={item.id}>{item.name}</div>
      ))}
    </div>
  );
}

export default Blog;

2. 服务端渲染(SSR)- getServerSideProps

适合数据需要实时更新的场景,每次用户请求时在服务器端获取最新数据:

// pages/blog.js
// 该函数在每次用户请求时执行(服务器端)
export async function getServerSideProps() {
  const res = await fetch('https://你的API地址/articles');
  const articles = await res.json();

  return {
    props: { articles },
  };
}

function Blog({ articles }) {
  return (
    <div>
      {articles.map((item) => (
        <div key={item.id}>{item.name}</div>
      ))}
    </div>
  );
}

export default Blog;

3. 客户端兜底:可选链避免报错

如果必须在客户端获取数据,除了加载状态,还可以用可选链操作符?.避免blog.articles为undefined时的报错,但这仅为兜底方案,仍建议配合加载状态使用:

{blog.articles?.map((item) => (
  <div key={item.id}>{item.name}</div>
))}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:53:22