'Routes not working in react even when trying to use Routes and Router

I'm following this tutorial: https://ibaslogic.com/routing-with-react-router/

When I render the page, I recieve this error

Uncaught Error: A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.
    at invariant (bundle.js:61876)
    at Route (bundle.js:62025)
    at renderWithHooks (bundle.js:23504)
    at mountIndeterminateComponent (bundle.js:26266)
    at beginWork (bundle.js:27465)
    at HTMLUnknownElement.callCallback (bundle.js:12454)
    at Object.invokeGuardedCallbackDev (bundle.js:12503)
    at invokeGuardedCallback (bundle.js:12563)
    at beginWork$1 (bundle.js:32305)
    at performUnitOfWork (bundle.js:31141)

I've tried to wrap the Route in Routes as the warning suggests. I still get an error that I need Router which I already have. I've also tried the suggestions here react-router, routes not working without success

Here is my js component file where the error is taking place:

import React, { useState, useEffect } from "react"
import TodosList from "./TodosList";
import Header from "./Header";
import InputTodo from "./InputTodo";
import { v4 as uuidv4 } from "uuid";
import "./App.css"
import { Route, Switch } from "react-router-dom"

const TodoContainer = () => {
  const [todos, setTodos] = useState(getInitialTodos())

  const handleChange = id => {
    setTodos(prevState =>
      prevState.map(todo => {
        if (todo.id === id) {
          return {
            ...todo,
            completed: !todo.completed,
          }
        }
        return todo
      })
    )
  }

  const delTodo = id => {
    setTodos([
      ...todos.filter(todo => {
        return todo.id !== id
      }),
    ])
  }

  const addTodoItem = title => {
    const newTodo = {
      id: uuidv4(),
      title: title,
      completed: false,
    }
    setTodos([...todos, newTodo])
  }

  const setUpdate = (updatedTitle, id) => {
    setTodos(
      todos.map(todo => {
        if (todo.id === id) {
          todo.title = updatedTitle
        }
        return todo
      })
    )
  }

  // useEffect(() => {
  //   console.log("test run")
  
  //   // getting stored items
  //   const temp = localStorage.getItem("todos")
  //   const loadedTodos = JSON.parse(temp)
  
  //   if (loadedTodos) {
  //     setTodos(loadedTodos)
  //   }
  // }, [])

  function getInitialTodos() {
    // getting stored items
    const temp = localStorage.getItem("todos")
    const savedTodos = JSON.parse(temp)
    return savedTodos || []
  }

  useEffect(() => {
    // storing todos items
    const temp = JSON.stringify(todos)
    localStorage.setItem("todos", temp)
  }, [todos])

  

  return (
    <Route path="/">
      <div className="container">
        <div className="inner">
          <Header />
          <InputTodo addTodoProps={addTodoItem} />
          <TodosList
            todos={todos}
            handleChangeProps={handleChange}
            deleteTodoProps={delTodo}
            setUpdate={setUpdate}
          />
        </div>
      </div>
    </Route>
  )
}

export default TodoContainer

Here is my index.js:

import React from "react"
import ReactDOM from "react-dom"
//component file
import TodoContainer from "./functionBased/components/TodoContainer"
import { BrowserRouter as Router } from "react-router-dom"

//stylesheet
import "./functionBased/App.css"

ReactDOM.render(
  <React.StrictMode>
    <Router>
      <TodoContainer />
    </Router>
  </React.StrictMode>,
  document.getElementById("root")
)

I'm unsure how to make Route work.



Solution 1:[1]

You are supposed to declare your Route in the Routes component. So you should first wrap the TodoContainer in the Routes component and then put the element you want to render in the element property of the Route component

ReactDOM.render(
  <React.StrictMode>
    <Router>
      <Routes>
        <Route path="/" element={<TodoContainer />}/>
      </Routes>
    </Router>
  </React.StrictMode>,
  document.getElementById("root")
)

Then, you don't need to handle the routing anymore in the TodoContainer

Take a look at the documentation to learn more about routing (this is the react router v6 here)

Solution 2:[2]

Not sure I understand the problem correctly but maybe try in the index.js to change

<TodoContainer />

with:

<Route exact path="/" element={<TodoContainer />}/>

also remember to import Route from react-router-dom

import {BrowserRouter as Router, Route} from 'react-router-dom';

This blogpost by Esteban Herrera gives a good example on how to use react router. https://blog.logrocket.com/react-router-dom-tutorial-examples/

Solution 3:[3]

I think you need to do something like that:

  • remove Route tag from your component folder
  • add Route tag to your index.js file like that
import {BrowserRouter as Router, Route} from 'react-router-dom';

...

 <Router>
     <Route exact path="/" element={<TodoContainer />}/>
 </Router>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 TheTisiboth
Solution 2 jamie.russell450
Solution 3 Ahmed Khaled