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

Next.js部署Vercel后详情页无数据但投票页正常求助

Next.js部署Vercel后详情页无法读取IndexedDB(Dexie.js)数据

问题现象

本地开发时应用功能完全正常,部署到Vercel后出现如下异常:

  • 详情页面无法从IndexedDB获取并展示数据,控制台无任何报错信息
  • 接收相同props的投票页面可正常读取并展示IndexedDB数据

核心原因分析

  1. 路由参数就绪时机差异:Vercel生产环境下,Next.js的路由预渲染机制可能导致详情页在router.query.id未完全加载时就执行数据查询,此时allItems.find无法匹配到数据,最终currentEvent为undefined。而投票页因存在交互触发的状态更新,会在路由参数就绪后重新渲染,从而能正确获取数据。
  2. 组件未处理数据未就绪状态:详情页直接使用currentEvent渲染,未等待数据加载完成或路由参数就绪,导致初始渲染时无数据展示。

解决方案

1. 等待路由参数就绪后再查询数据

修改详情页代码,通过useEffect监听路由参数id和allItems的变化,确保两者都就绪后再查找对应事件数据:

import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import DetailsEventData from "@/components/DetailsEventData";
import { optionIcons } from "@/Icons/optionIcon";

function DetailsPage({ allItems }) {
    const router = useRouter();
    const { id } = router.query;
    const [currentEvent, setCurrentEvent] = useState(null);

    useEffect(() => {
        // 确保id和allItems都存在时再查询
        if (id && allItems?.length) {
            const matchedEvent = allItems.find(item => item.eventId === id);
            setCurrentEvent(matchedEvent);
        }
    }, [id, allItems]);

    // 数据未就绪时显示加载状态
    if (!currentEvent) {
        return <div>加载中...</div>;
    }

    function handelEdit() {
        router.push(`/editpage/${currentEvent.eventId}`);
    }

    return (
        <StyledMain>
            <StyledBackLink href={`/`}>
                <Image
                    src={optionIcons[3].imageSrc}
                    alt={optionIcons[3].description}
                    width={40}
                    height={50}
                />
            </StyledBackLink>

            <StyledTitle>Event Details</StyledTitle>
            <DetailsEventData currentEvent={currentEvent} />

            <StyledEditImage
                onClick={handelEdit}
                src={optionIcons[5].imageSrc}
                alt={optionIcons[5].description}
                width={55}
                height={55}
            />
        </StyledMain>
    );
}

export default DetailsPage;

2. 优化数据加载的容错处理

在_app.js中添加数据加载状态,确保allItems就绪后再渲染子页面:

import { v4 as uuidv4 } from "uuid";
import { useLiveQuery } from "dexie-react-hooks";
import { db } from "@/components/Dexie";

const { eventDetails } = db;

export default function App({ Component, pageProps }) {
    const allItems = useLiveQuery(() => eventDetails.toArray(), []);

    // 等待数据库数据加载完成
    if (!allItems) {
        return <div>全局加载中...</div>;
    }

    async function handleEntryData(data) {
        try {
            await db.eventDetails.add({
                eventId: uuidv4(),
                title: data.title,
                startTime: data.startTime,
                endTime: data.endTime,
                location: data.location,
                introduce: data.introduce,
                creator: data.creator,
            });
        } catch (error) {
            alert(`Error: ${error}`);
        }
    }

    return (
        <>
            <GlobalStyle />
            <Head></Head>
            <main>
                <Component
                    {...pageProps}
                    allItems={allItems}
                    onHandleEntryData={handleEntryData}
                />
            </main>
        </>
    );
}

3. 强化详情页展示组件的容错性

修改DetailsEventData组件,确保在currentEvent未就绪时显示友好提示:

import { voteIcons } from "@/Icons/dataIcons";

export default function DetailsEventData({ currentEvent }) {
    if (!currentEvent) {
        return <div>加载事件详情中...</div>;
    }

    return (
        <StyledDetailsCard>
            <StyledListItem>
                {!currentEvent.voteResult ? (
                    "Are You there?"
                ) : (
                    <Image
                        src={voteIcons[currentEvent.voteResult].imageSrc}
                        alt={voteIcons[currentEvent.voteResult].description}
                        width={30}
                        height={30}
                    />
                )}
            </StyledListItem> 
            <StyledListItem>{currentEvent.title}</StyledListItem>
            <StyledListItem>{currentEvent.startTime}</StyledListItem>
            <StyledListItem>{currentEvent.endTime}</StyledListItem>
            <StyledListItem>{currentEvent.location}</StyledListItem>
            <StyledListItem>{currentEvent.introduce}</StyledListItem>
            <StyledListItem>{currentEvent.creator}</StyledListItem>
        </StyledDetailsCard>
    );
}

4. 验证客户端数据一致性

注意IndexedDB是客户端本地存储,部署到Vercel后,新访问的浏览器环境中IndexedDB是空的,需要通过前端操作(比如创建事件)重新添加数据,不要依赖本地开发时的测试数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 13:47:02