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

开发StackOverflow克隆网站:修复两处Uncaught TypeError报错

StackOverflow克隆网站报错修复求助

当前开发StackOverflow克隆网站时遇到两个错误:

  1. Navbar.js中出现Uncaught TypeError: Cannot read properties of undefined (reading 'result')
  2. Homebar.js中出现Uncaught TypeError: Cannot read properties of undefined (reading 'data')
    首页显示空白,仅控制台输出上述错误。

Homebar.js代码

import React from "react";

import { useSelector } from "react-redux";
import QuestionList from "./QuestionList";
import "./Homebar";
import { useLocation, useNavigate } from "react-router-dom";

function Homebar() {
  const location = useLocation();
  const user = 1;
  const navigate = useNavigate();

  const questionsList = useSelector((state) => state.questionsReducer);
  // console.log(questionsList)
  // var questionsList = [{
  //     _id: 1,
  //     upVotes: 3,
  //     downVotes: 2,
  //     noOfAnswers: 2,
  //     questionTitle: "What is a function?",
  //     questionBody: "It meant to be",
  //     questionTags: ["java", "node js", "react js", "mongo db", "express js"],
  //     userPosted: "mano",
  //     userId: 1,
  //     askedOn: "jan 1",
  //     answer: [{
  //         answerBody: "Answer",
  //         userAnswered: 'kumar',
  //         answeredOn: "jan 2",
  //         userId: 2,
  //     }]
  // },{
  //     _id: 2,
  //     upVotes: 3,
  //     downVotes: 2,
  //     noOfAnswers: 0,
  //     questionTitle: "What is a function?",
  //     questionBody: "It meant to be",
  //     questionTags: ["javascript", "R", "python"],
  //     userPosted: "mano",
  //     askedOn: "jan 1",
  //     userId: 1,
  //     answer: [{
  //         answerBody: "Answer",
  //         userAnswered: 'kumar',
  //         answeredOn: "jan 2",
  //         userId: 2,
  //     }]
  // },{
  //     _id: 3,
  //     upVotes: 3,
  //     downVotes: 2,
  //     noOfAnswers: 0,
  //     questionTitle: "What is a function?",
  //     questionBody: "It meant to be",
  //     questionTags: ["javascript", "R", "python"],
  //     userPosted: "mano",
  //     askedOn: "jan 1",
  //     userId: 1,
  //     answer: [{
  //         answerBody: "Answer",
  //         userAnswered: 'kumar',
  //         answeredOn: "jan 2",
  //         userId: 2,
  //     }]
  // }]

  const checkAuth = () => {
    if (user === null) {
      alert("login or signup to ask a question");
      navigate("/Auth");
    } else {
      navigate("/AskQuestion");
    }
  };

  return (
    <div className="main-bar">
      <div className="main-bar-header">
        {location.pathname === "/" ? (
          <h1>Top Questions</h1>
        ) : (
          <h1>All Questions</h1>
        )}
        <button onClick={checkAuth} className="ask-btn">
          Ask Question
        </button>
      </div>
      <div>
        {questionsList.data === null ? (
          <h1>Loading...</h1>
        ) : (
          <>
            <p>{questionsList.data.length} questions</p>
            <QuestionList questionsList={questionsList.data} />
          </>
        )}
      </div>
    </div>

  );
}

export default Homebar;
import React, { useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";
import SearchIcon from "@mui/icons-material/Search";
import { useDispatch, useSelector } from "react-redux";
import decode from "jwt-decode";
import { Button } from "@mui/material";
import "./Navbar.css";
import { setCurrentUser } from "../../Actions/CurrentUser";
import Avatar from "../Avatar/Avatar";

function Navbar() {
  const dispatch = useDispatch();
  var User = useSelector((state) => state.currentUserReducer);
  const navigate = useNavigate();

  const handleLogout = () => {
    dispatch({ type: "LOGOUT" });
    navigate("/");
    dispatch(setCurrentUser(null));
  };

  useEffect(() => {
    const token = User?.token;
    if (token) {
      const decodedToken = decode(token);
      if (decodedToken.exp * 1000 < new Date().getTime()) {
        handleLogout();
      }
    }
    dispatch(setCurrentUser(JSON.parse(localStorage.getItem("Profile"))));
  }, [User?.token, dispatch]);

  return (
    <nav>
      <div className="nav">
        <Link to="/">
          <div className="logo">
            <img
              src="https://www.vectorlogo.zone/logos/stackoverflow/stackoverflow-official.svg"
              alt="logo"
            />
          </div>
        </Link>
        <div className="about">
          <p>About</p>
        </div>
        <div className="Products">
          <p>Products</p>
        </div>
        <div className="For-teams">
          <p>For Teams</p>
        </div>
        <div className="auth">
          <div className="search">
            <SearchIcon />
            <input type="text" placeholder="Search..." />
          </div>
          {User === null ? (
            <></>
          ) : (
            <>
              <div className="login">
                <Link to="/auth">
                  <Button
                    style={{
                      height: "2rem",
                      background: " hsl(205,46%,92%)",
                      color: "#2C5877",
                      fontSize: "0.813rem",
                      textTransform: "capitalize",
                      border: "0.063rem solid #7AA7C7",
                      top: "0.5rem",
                      marginLeft: "10px",
                      textDecoration: "none",
                    }}
                  >
                    Login
                  </Button>
                </Link>{" "}
                :
                <Avatar
                  backgroundColor="#009dff"
                  px="10px"
                  py="7px"
                  borderRadius="50%"
                  color="white"
                >
                  <Link
                    to={`/Users/${User?.result?._id}`}
                    style={{ color: "white", textDecoration: "none" }}
                  >
                    {User.result.name.charAt(0).toUpperCase()}
                  </Link>
                </Avatar>
                <button className="nav-item nav-links" onClick={handleLogout}>
                  Log out
                </button>
              </div>
              <Link to="/auth">
                <div className="signup">
                  <Button
                    style={{
                      height: "2rem",
                      background: " #0074CC",
                      color: "white",
                      fontSize: "0.813rem",
                      textTransform: "capitalize",
                      top: "0.5rem",
                      marginLeft: "10px",
                      textDecoration: "none",
                    }}
                  >
                    Sign Up
                  </Button>
                </div>
              </Link>
            </>
          )}
        </div>
      </div>
    </nav>
  );
}

export default Navbar;

解决方案

1. 修复Navbar.js中的result读取错误

问题本质

未登录时User为null或undefined,原逻辑判断错误(未登录时不渲染任何按钮,已登录却显示登录/注册按钮),且直接访问User.result会触发属性读取错误。

修复代码

替换Navbar.js中auth区域的条件渲染逻辑,同时用可选链处理嵌套属性:

<div className="auth">
  <div className="search">
    <SearchIcon />
    <input type="text" placeholder="Search..." />
  </div>
  {/* 未登录状态:显示登录、注册按钮 */}
  {!User ? (
    <>
      <Link to="/auth">
        <Button
          style={{
            height: "2rem",
            background: " hsl(205,46%,92%)",
            color: "#2C5877",
            fontSize: "0.813rem",
            textTransform: "capitalize",
            border: "0.063rem solid #7AA7C7",
            top: "0.5rem",
            marginLeft: "10px",
            textDecoration: "none",
          }}
        >
          Login
        </Button>
      </Link>
      <Link to="/auth">
        <div className="signup">
          <Button
            style={{
              height: "2rem",
              background: " #0074CC",
              color: "white",
              fontSize: "0.813rem",
              textTransform: "capitalize",
              top: "0.5rem",
              marginLeft: "10px",
              textDecoration: "none",
            }}
          >
            Sign Up
          </Button>
        </div>
      </Link>
    </>
  ) : (
    // 已登录状态:显示头像、退出按钮
    <>
      <div className="login">
        <Avatar
          backgroundColor="#009dff"
          px="10px"
          py="7px"
          borderRadius="50%"
          color="white"
        >
          <Link
            to={`/Users/${User?.result?._id}`}
            style={{ color: "white", textDecoration: "none" }}
          >
            {User?.result?.name?.charAt(0).toUpperCase() || 'U'}
          </Link>
        </Avatar>
        <button className="nav-item nav-links" onClick={handleLogout}>
          Log out
        </button>
      </div>
    </>
  )}
</div>

同时修正useEffect中的token校验逻辑:

useEffect(() => {
  const profile = JSON.parse(localStorage.getItem("Profile"));
  dispatch(setCurrentUser(profile));
  
  // 仅当存在有效用户数据时校验token
  if (profile?.token) {
    const decodedToken = decode(profile.token);
    if (decodedToken.exp * 1000 < new Date().getTime()) {
      handleLogout();
    }
  }
}, [dispatch]);

2. 修复Homebar.js中的data读取错误

问题本质

Redux中questionsReducer的初始状态可能未定义data属性,或questionsList本身为undefined,直接访问questionsList.data会触发报错,且原加载判断逻辑无法覆盖初始状态。

修复代码

修改Homebar.js中的列表渲染逻辑:

<div>
  {/* 先判断数据是否加载完成,未完成则显示加载状态 */}
  {!questionsList || !questionsList.data ? (
    <h1>Loading...</h1>
  ) : (
    <>
      <p>{questionsList.data.length} questions</p>
      <QuestionList questionsList={questionsList.data} />
    </>
  )}
</div>

同时建议在questionsReducer中设置初始状态,避免数据未加载时出现undefined:

// questionsReducer示例
const initialState = {
  data: []
};

export default function questionsReducer(state = initialState, action) {
  switch(action.type) {
    case "FETCH_QUESTIONS":
      return { ...state, data: action.payload };
    default:
      return state;
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 14:10:47