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

React博客详情页:ID不存在时无法跳转至404页面问题求助

问题分析与修复方案

核心问题

  1. 状态初始化与未处理报错:初始myData设为{},当找不到对应ID的博客时,data.find()返回undefined,执行setData(undefined)后,myData变为undefined,此时访问myData.id会抛出Cannot read properties of undefined (reading 'id')的错误,导致重定向逻辑无法触发。
  2. 依赖项冗余:第一个useEffect的依赖数组中加入了setData和setIsLoading,这两个是React内置的状态更新函数,本身稳定无需作为依赖,会引发不必要的重复渲染。
  3. 不符合单页应用的重定向方式:使用window.location.replace会刷新页面,应该用React Router提供的useNavigate钩子实现无刷新跳转。
  4. 无效异步日志:setData是异步操作,之后立刻console.log(myData)打印的是旧状态,没有实际意义。

修复后的代码

import { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom'; // 引入useNavigate
import './styles/detail.css'
import PostHero from '../components/design/PostHero/PostHero';
import HistoryButton from '../components/design/HistertButton/HistoryButton';


const Detail = () => {
    // 初始设为null,清晰区分未加载和未找到的状态
    const [myData, setData] = useState(null); 
    const { id } = useParams();
    const [isLoading, setIsLoading] = useState(true);
    const navigate = useNavigate(); // 初始化导航钩子

    useEffect(() => {
        let isActive = true;
        fetch('../blogs.json')
        .then(response => {
            // 处理请求失败的情况
            if (!response.ok) throw new Error('请求失败');
            return response.json();
        })
        .then(data => {
            if (isActive) {
                const foundPost = data.find(post => post.id == id);
                setData(foundPost);
                setIsLoading(false);
            }
        })
        .catch(err => {
            // 捕获请求错误,比如JSON文件不存在的情况
            console.error(err);
            setIsLoading(false);
        })
        return () => isActive = false;
    }, [id]); // 移除冗余依赖

    useEffect(() => {
        if (!isLoading) {
            // myData为null或undefined时,说明未找到博客,执行重定向
            if (!myData) {
                navigate('/not-found');
            }
        }
    }, [myData, isLoading, navigate]);

    // 加载状态显示提示,避免页面空白
    if (isLoading) {
        return <div>加载中...</div>;
    }

    // 未找到博客时返回null,此时已触发重定向
    if (!myData) {
        return null;
    }

    return (
        <div className='blog-detail'>
            <PostHero id={myData.id}/>
            <div className='post-container'>
                <div>
                    <div className='content-header'>
                        <h2 className='post-title'>{myData.titel}</h2>
                        <HistoryButton />
                    </div>
                    <span className='post-date'>{myData.datum}</span>
                    <ul className='post-tags'>
                        {myData.tags?.map((tag,index) => (
                            <div className='li-item' key={index}>
                                <div className='li-indicator' style={{backgroundColor: `var(--${tag})`}}/>
                                <li>{tag}</li>
                            </div>
                        ))}
                    </ul>
                </div>
                <div className='content-container'>
                    <div className='post-tekst'>
                        {myData.description}
                    </div>
                    <div className='detail-photos'>
                        {myData.detail_images?.map((img, index) => (
                            <div className='detail-image' key={index}>
                                <img src={`../../../${img}`} alt="博客详情图"/>
                            </div>
                        ))}
                    </div>
                </div>
            </div>
        </div>
    )
}

export default Detail;

关键修改说明

  1. 状态初始化调整:将myData初始值改为null,明确区分“未加载”和“未找到博客”的状态。
  2. 依赖项优化:只保留id作为第一个useEffect的依赖,避免不必要的重渲染。
  3. 正确重定向方式:使用useNavigate替代window.location.replace,符合单页应用的路由跳转规范。
  4. 错误处理增强:添加请求失败的捕获逻辑,同时在渲染阶段增加加载提示,提升用户体验。
  5. 简化条件判断:直接通过!myData判断是否未找到博客,避免访问myData.id导致的报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:42:38