开发StackOverflow克隆网站:修复两处Uncaught TypeError报错
StackOverflow克隆网站报错修复求助
当前开发StackOverflow克隆网站时遇到两个错误:
- Navbar.js中出现
Uncaught TypeError: Cannot read properties of undefined (reading 'result') - 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;
Navbar.js代码
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
相关产品推荐
相关产品推荐

