Tanstack Router: Cannot read properties of undefined problem

465 views Asked by At

I am currently trying to implement routing in my application using the new Tanstack Router ( "@tanstack/react-router": "^1.4.6) . Whenever I click the 'Exercise Tracker' link component I get the following error:

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

Here are my components

Index.tsx contains all the needed code for setting up the new router

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")
);

Clicking the exercise tracker button triggers the error

//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;

Any help would be apricated

0

There are 0 answers