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

如何在获取服务器数据后渲染React组件?问题排查

解决方案

你的问题核心是异步获取用户数据时,组件已完成初始渲染,导致Home组件一开始拿不到有效数据。可以通过添加加载状态解决,同时React本身会在状态更新时自动触发重渲染,确保数据就绪后组件能同步更新内容。

步骤1:在Layout中添加加载状态

修改Layout.js,增加加载状态标记,在数据获取完成前显示加载提示,避免渲染未填充的内容:

import React, { useEffect, useState } from 'react';
import { Outlet } from "react-router-dom";
import Navbar from './Navbar';

function Layout() {
  const [currentUser, setCurrentUser] = useState({
    name: "",
    email: "",
    signedIn: false,
    admin: false
  });
  // 新增加载状态,初始为true
  const [isLoading, setIsLoading] = useState(true);

  const getCurrentUser = async () => {
    try {
      const res = await fetch('/userinfo', {
        method: "GET",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json"
        },
        credentials: "include"
      });

      const data = await res.json()

      if (res.status !== 200 || !data) {
        const error = new Error(res.error);
        throw error;
      } else {
        const { name, email, admin } = data.userInfo;
        setCurrentUser({name, email, admin, signedIn: true});
      }
    } catch (err) {
      console.log(err.message);
      // 请求失败时保持默认用户状态,可根据需求调整
    } finally {
      // 无论请求成功或失败,都结束加载状态
      setIsLoading(false);
    }
  };

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

  const setUserInfo = (data) => {
    setCurrentUser(data);
  };

  // 加载中时显示加载提示
  if (isLoading) {
    return <div className="flex justify-center items-center h-screen">加载中...</div>;
  }

  return (
    <div>
      <Navbar signedInfo={currentUser} setSignedInfo={setUserInfo} />
      <div>
        <Outlet context={[currentUser, setUserInfo]} />
      </div>
    </div>
  );
}

export default Layout;

步骤2:优化Home组件的初始渲染(可选)

如果不想完全隐藏内容,也可以在Home组件中判断用户登录状态,避免显示空的用户名:

import React from 'react'
import { useNavigate, useOutletContext } from 'react-router-dom'

function Home() {
  const navigate = useNavigate();
  const [currentUser] = useOutletContext();

  const redirectTo = () => {
    if(currentUser.signedIn) {
      navigate('/labs');
    } else {
      navigate('/signin')
    }
  }

  return (
    <div className='flex flex-col items-center space-y-10 animate-fadeIn'>
      <h1 className="text-3xl pt-32 text-center font-semibold font-sans md:text-4xl lg:text-5xl">
        Welcome 
        {/* 仅在用户登录时显示用户名 */}
        <span className='text-blue-500'>{currentUser.signedIn ? ` ${currentUser.name}` : ''}</span>
        <br /> To Control System Engineering Labs
      </h1>
      <p className='text-center mx-5 md:max-w-3xl'>Control systems are everywhere, from the tiniest dial functioning inside your watch to the gigantic satellite revolving around the planet. They constantly synchronise the behaviour of devices in a recurrent and predicted way.</p>
      <button onClick={redirectTo} className="inline-block px-4 py-2 text-white bg-blue-600 rounded-md shadow hover:bg-blue-700 focus:bg-blue-700 focus-outline:none active:bg-blue-800 transition duration-150 ease-in-out">Get Started</button>
    </div>
  )
}

export default Home

原理说明

  • 当getCurrentUser异步请求完成后,setCurrentUser会更新Layout的状态,触发Layout重渲染,此时Outlet的context同步更新,Home组件通过useOutletContext获取到最新用户数据,自动触发重渲染。
  • 加载状态的作用是在数据未就绪时,避免渲染不完整内容,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 06:24:05