使用Tanstack Router时出现Cannot read properties of undefined错误求助
Tanstack Router v1.4.6 路由跳转报错:Cannot read properties of undefined (reading 'routeId')
错误信息
Cannot read properties of undefined (reading 'routeId') TypeError: Cannot read properties of undefined (reading 'routeId') at http://localhost:3000/static/js/bundle.js:1449:89 at J (http://localhost:3000/static/js/bundle.js:1450:9) at St (http://localhost:3000/static/js/bundle.js:1759:11) at http://localhost:3000/static/js/bundle.js:1878:15 at renderWithHooks (http://localhost:3000/static/js/bundle.js:22462:22) at updateForwardRef (http://localhost:3000/static/js/bundle.js:25031:24) at beginWork (http://localhost:3000/static/js/bundle.js:27078:20) at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:12058:18) at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:12102:20) at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:12159:35) ERROR Invariant failed at g (http://localhost:3000/static/js/bundle.js:1101:19) at K (http://localhost:3000/static/js/bundle.js:1361:5) at renderWithHooks (http://localhost:3000/static/js/bundle.js:22462:22) at updateFunctionComponent (http://localhost:3000/static/js/bundle.js:25342:24) at beginWork (http://localhost:3000/static/js/bundle.js:27054:20) at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:12058:18) at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:12102:20) at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:12159:35) at beginWork$1 (http://localhost:3000/static/js/bundle.js:32023:11) at performUnitOfWork (http://localhost:3000/static/js/bundle.js:31271:16)
代码实现
index.tsx(路由配置)
import React from "react"; import ReactDOM from "react-dom"; import { ApolloProvider } from "@apollo/client"; import client from "./client"; import App from "./App"; import { Outlet, RootRoute, Route, Router, RouterProvider, } from "@tanstack/react-router"; import ExerciseTracker from "./ExerciseTracker"; const RootRouter = new RootRoute({ component: () => ( <> <Outlet /> </> ), }); const landingPageRoute = new Route({ getParentRoute: () => RootRouter, path: "/", component: () => <App />, }); const exerciseTrackerRoute = new Route({ getParentRoute: () => RootRouter, path: "/exercise", component: () => <ExerciseTracker />, }); const routeTree = RootRouter.addChildren([ landingPageRoute, exerciseTrackerRoute, ]); const router = new Router({ routeTree }); declare module "@tanstack/react-router" { interface Router { router: typeof router; } } ReactDOM.render( <ApolloProvider client={client}> <RouterProvider router={router} /> </ApolloProvider>, document.getElementById("root") );
App.tsx(首页组件)
import React from "react"; import { Link} from "@tanstack/react-router"; const App = () => { return ( <> <h1>Welcome to Gym App</h1> <h2>Choose a page to navigate to:</h2> <button> <Link to="/exercise">Exercise tracker</Link> </button> </> ); }; export default App;
ExerciseTracker.tsx(目标页面组件)
import React, { useState } from "react"; import { GET_EXERCISES } from "./Queries/Queries"; import { CREATE_EXERCISE, DELETE_EXERCISE } from "./Mutations/Mutations"; import { useQuery, useMutation } from "@apollo/client"; function ExerciseTracker() { const [newExerciseName, setNewExerciseName] = useState(""); const [newMuscleTrained, setNewMuscleTrained] = useState(""); const { loading, error, data = [], refetch } = useQuery(GET_EXERCISES); const [createExercise] = useMutation(CREATE_EXERCISE); const [deleteExercise] = useMutation(DELETE_EXERCISE); const handleCreateExercise = async (e: any) => { e.preventDefault(); try { const { data = [] } = await createExercise({ variables: { name: newExerciseName, muscletrained: newMuscleTrained, }, }); console.log("Mutation response:", data); if (data && data.createExercise) { console.log("Created exercise:", data.createExercise); refetch(); setNewExerciseName(""); setNewMuscleTrained(""); } else { console.error("Failed to create exercise. No data returned."); } } catch (error: any) { console.error("Error creating exercise:", error.message); } }; const handleDeleteExercise = async (id: string) => { try { const { data } = await deleteExercise({ variables: { id, }, }); console.log("Mutation response:", data); if (data && data.deleteExercise) { console.log("Deleted exercise with ID:", data.deleteExercise); refetch(); } else { console.error("Failed to delete exercise. No data returned."); } } catch (error: any) { console.error("Error deleting exercise:", error.message); } }; if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error.message}</p>; return ( <div> <h1>Exercise Library</h1> <div> <h2>Create a New Exercise</h2> <label> Name: <input placeholder="Exercise Name" className="exerciseInput" aria-label="exerciseInput" type="text" value={newExerciseName} onChange={(e) => { setNewExerciseName(e.target.value); }} /> </label> <label> Muscle Trained: <input placeholder="Muscle Trained" className="muscleInput" aria-label="muscleInput" type="text" value={newMuscleTrained} onChange={(e) => setNewMuscleTrained(e.target.value)} /> </label> <button onClick={handleCreateExercise}>Create Exercise</button> </div> <h2>Exercises</h2> {data.exercises.map((exercise: any) => ( <div key={exercise.id}> <h3>{exercise.name}</h3> <p>Muscle Trained: {exercise.muscletrained}</p> <button onClick={() => handleDeleteExercise(exercise.id)}> Delete Exercise </button> </div> ))} </div> ); } export default ExerciseTracker;
问题分析与解决方案
核心问题
错误根源在于类型声明错误。在Tanstack Router v1中,扩展路由类型需要使用Register接口,而非Router接口。错误的类型声明会导致路由上下文无法正确传递,触发routeId未定义的报错。
修复步骤
- 修正类型声明:
将index.tsx中的类型声明部分替换为:
declare module "@tanstack/react-router" { interface Register { router: typeof router; } }
- (可选)升级React渲染方式:
如果使用React 18,建议将ReactDOM.render替换为createRoot,避免潜在的兼容性问题:
import { createRoot } from 'react-dom/client'; const root = createRoot(document.getElementById('root')!); root.render( <ApolloProvider client={client}> <RouterProvider router={router} /> </ApolloProvider> );
- 验证Link组件使用:
确保Link组件直接来自@tanstack/react-router,且没有被错误封装。当前App.tsx中的Link使用是正确的,无需修改。
验证修复
修改后重新启动项目,点击"Exercise tracker"链接即可正常跳转至目标页面,不会再出现routeId未定义的错误。
内容的提问来源于stack exchange,提问作者julek5119
相关产品推荐
相关产品推荐

