React异步加载MongoDB数据致组件延迟渲染问题求助
解决方案
1. 将数据请求从sitemap.ts迁移至组件内部
sitemap.ts的核心作用是生成静态路由结构,并不适合用来处理给组件提供动态内容的异步请求。建议直接在首页的My Photos板块组件内发起数据请求:
import { useState, useEffect } from 'react'; import axios from 'axios'; import Lightbox from 'yet-another-react-lightbox'; const HomeMyPhotosSection = () => { const [photos, setPhotos] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const fetchPhotos = async () => { try { // 替换为你的MongoDB数据接口地址 const res = await axios.get('/api/album-photos'); setPhotos(res.data); } catch (err) { console.error('相册数据加载失败:', err); } finally { setIsLoading(false); } }; fetchPhotos(); }, []); return ( <div className="my-photos-section"> {isLoading ? ( <div>加载中...</div> ) : photos.length > 0 ? ( <> {/* 渲染照片缩略图列表 */} <div className="photos-grid"> {photos.map(photo => ( <img key={photo._id} src={photo.thumbnail} alt={photo.name} /> ))} </div> {/* 集成yet-another-react-lightbox */} <Lightbox slides={photos.map(p => ({ src: p.fullUrl }))} // 其他lightbox配置项 /> </> ) : ( <div>暂无照片</div> )} </div> ); }; export default HomeMyPhotosSection;
2. 用全局状态管理同步数据(若需跨组件共享)
如果必须在路由配置阶段处理数据,可通过Context API或Redux实现全局数据同步,确保组件能感知到数据变化并重新渲染:
第一步:创建相册数据Context
// PhotoContext.tsx import { createContext, useContext, useState, useEffect, ReactNode } from 'react'; import axios from 'axios'; interface PhotoContextProps { photos: any[]; isLoading: boolean; } const PhotoContext = createContext<PhotoContextProps | undefined>(undefined); export const PhotoProvider = ({ children }: { children: ReactNode }) => { const [photos, setPhotos] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const fetchPhotos = async () => { try { const res = await axios.get('/api/album-photos'); setPhotos(res.data); } catch (err) { console.error('相册数据加载失败:', err); } finally { setIsLoading(false); } }; fetchPhotos(); }, []); return ( <PhotoContext.Provider value={{ photos, isLoading }}> {children} </PhotoContext.Provider> ); }; export const usePhotos = () => { const context = useContext(PhotoContext); if (!context) { throw new Error('usePhotos必须在PhotoProvider包裹的组件内使用'); } return context; };
第二步:在根组件中注入Provider
// App.tsx import { PhotoProvider } from './PhotoContext'; import { BrowserRouter } from 'react-router-dom'; function App() { return ( <BrowserRouter> <PhotoProvider> {/* 你的路由与组件内容 */} </PhotoProvider> </BrowserRouter> ); }
第三步:在首页组件中使用全局数据
import { usePhotos } from './PhotoContext'; const HomeMyPhotosSection = () => { const { photos, isLoading } = usePhotos(); return ( <div className="my-photos-section"> {isLoading ? ( <div>加载中...</div> ) : photos.length > 0 ? ( <div className="photos-grid"> {photos.map(photo => ( <img key={photo._id} src={photo.thumbnail} alt={photo.name} /> ))} </div> ) : ( <div>暂无照片</div> )} </div> ); };
3. 适配Next.js等框架的预渲染逻辑(若使用)
如果是Next.js项目,首页若采用静态生成,需用getStaticProps预获取数据,而非在sitemap.ts中处理:
// pages/index.tsx import axios from 'axios'; import HomeMyPhotosSection from '../components/HomeMyPhotosSection'; export async function getStaticProps() { let initialPhotos = []; try { const res = await axios.get('你的MongoDB数据接口地址'); initialPhotos = res.data; } catch (err) { console.error('相册数据加载失败:', err); } return { props: { initialPhotos }, revalidate: 60 // 可选,每隔60秒重新生成页面 }; } const Home = ({ initialPhotos }) => { return ( <div className="home-page"> {/* 其他首页内容 */} <HomeMyPhotosSection initialPhotos={initialPhotos} /> </div> ); }; export default Home;
内容的提问来源于stack exchange,提问作者Tung
相关产品推荐
相关产品推荐

