'The above error occurred in the <BrowserRouter> component, Invalid hook call
I'm trying to use a react-router, after using the library some problems begin, I've already tried to write different code, I found it ready-made on the Internet, but still something is wrong (even reset Windows). This code is taken from the official react-router documentation, did everything as written (https://reactrouter.com/docs/en/v6/getting-started/installation)
Here is the errors:
Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. >This could happen for one of the following reasons:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. printWarning @ react.development.js:207
Uncaught TypeError: Cannot read properties of null (reading 'useRef')
at useRef (react.development.js:1628:1)
at BrowserRouter (index.tsx:151:1)
at renderWithHooks (react-dom.development.js:16175:1)
at mountIndeterminateComponent (react-dom.development.js:20913:1)
at beginWork (react-dom.development.js:22416:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4161:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4210:1)
at invokeGuardedCallback (react-dom.development.js:4274:1)
at beginWork$1 (react-dom.development.js:27405:1)
at performUnitOfWork (react-dom.development.js:26513:1)
The above error occurred in the component:
at BrowserRouter (http://localhost:3001/static/js/bundle.js:45400:5)
Consider adding an error boundary to your tree to customize error handling behavior. Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. logCapturedError @ react-dom.development.js:18572
4 errors with invalid hooks, 3 errors with Uncaught TypeError: Cannot read properties of null (reading 'useRef') and The above error occurred in the <BrowserRouter> component appear in the console once
Here is my code:
src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter } from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
src./App.js
import React from "react";
import ReactDOM from "react-dom";
import {Routes,Route, Link } from "react-router-dom";
function App() {
return (
<div className="App">
<h1>Welcome to React Router!</h1>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Routes>
</div>
);
}
function Home() {
return (
<>
<main>
<h2>Welcome to the homepage!</h2>
<p>You can do this, I believe in you.</p>
</main>
<nav>
<Link to="/about">About</Link>
</nav>
</>
);
}
function About() {
return (
<>
<main>
<h2>Who are we?</h2>
<p>
That feels like an existential question, don't you
think?
</p>
</main>
<nav>
<Link to="/">Home</Link>
</nav>
</>
);
}
export default App;
and package.json
{
"name": "ao-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.2.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
I did everything as it is written in the documentation (https://reactrouter.com/docs/en/v6/getting-started/installation)
Solution 1:[1]
I was facing the same issue. Just uninstall the version 6 of the react-router-dom and install it like
npm i react-router-dom
This worked for me!
Solution 2:[2]
I wanted to see if I could make @riccardo-bucco's answer any faster (I could not) but I will show you an alternative that is basically the same speed that I thought might be faster.
To be clear, I feel the top answer is from @riccardo_bucco as it is easier to follow and is just as fast. Use it.
I was hoping that not having to scan the counter twice would more than make up for resetting the largest_with_ties list, but it did not.
def jonsg(data_in):
largest_with_ties = [(None, 0)]
for item in collections.Counter(data_in).items():
diff = item[1] - largest_with_ties[0][1]
if diff < 0:
continue
if diff > 0:
largest_with_ties.clear()
largest_with_ties.append(item)
return sorted(largest_with_ties)
Testing the timings I will use the words from "The Complete Works of William Shakespeare" from Project Guttenberg. You can get that here (5.5m): https://www.gutenberg.org/files/100/100-0.txt
Note, I have slightly altered Riccardo Bucco's answer to return a tuple not that it made a performance difference.
import timeit
setup = """
import collections
#data_in = ['b', 'b', 'a', 'a', 'c']
with open("shakespeare.txt", "r", encoding="utf-8") as file_in:
data_in = [word.strip().lower() for line in file_in for word in line.split()]
def riccardo_bucco(data_in):
counts = collections.Counter(data_in) # O(n)
largest = max(counts.values()) # O(n)
largest_with_ties = [item for item in counts.items() if item[1] == largest] # O(n)
return sorted(largest_with_ties)
def jonsg(data_in):
largest_with_ties = [(None, 0)]
for item in collections.Counter(data_in).items():
diff = item[1] - largest_with_ties[0][1]
if diff < 0:
continue
if diff > 0:
largest_with_ties.clear()
largest_with_ties.append(item)
return sorted(largest_with_ties)
"""
Now we can run:
print(f"riccardo_bucco: {timeit.timeit('riccardo_bucco(data_in)', setup=setup, number=100)}")
print(f"jonsg : {timeit.timeit('jonsg(data_in)', setup=setup, number=100)}")
giving results like:
riccardo_bucco: 10.59
jonsg : 10.55
Suggesting to me that they perform equally well (or poorly). Feel free to extend this with other attempts.
FYI: The actual most common is: ('the', 30087).
If one wants to test with the individual characters then data_in can be set via:
data_in = [char.lower() for char in file_in.read() if char.strip()]
In that case the most common is [('e', 482212)]
But doing so does not fundamentally alter the relative performance of these solutions.
Solution 3:[3]
Using your code and Counter we get the following:
from collections import Counter
def most_frequent(List):
occurence_count = Counter(List)
return occurence_count.most_common()
l = ['b', 'b', 'b', 'a', 'a', 'c']
print(sorted(most_frequent(l)))
We get the output:
[('a', 2), ('b', 3), ('c', 1)]
With sorted we sort the items automatically by alphabet.
You can double check that its sorting alphabetically with the following code:
tuplesInList = (most_frequent(l))
#to sort tuples within lists we use an anonymous function(lambda)
def sort_tuple_vals(my_tup):
my_tup.sort(key=lambda x:x[0])
return my_tup
This sorts the tuples by the first element in the tuple
print(sort_tuple_vals(tuplesInList))
gets the output
[('a', 2), ('b', 3), ('c', 1)]
If you want to sort by occurrence as opposed to alphabetically, then sort by alphabetically in case of a tie, the following code should work. We first sort the tuples by the number of occurrences with lambda x: x[1]
tuplesInList = (most_frequent(l))
#to sort tuples within lists we use an anonymous function(lambda)
def sortTupsbyOccurance(my_tup):
my_tup.sort(key=lambda x:x[1])
print(my_tup)
return my_tup
tuple=(sortTupsbyOccurance(tuplesInList))
print(tuple)
from an initial list l = ['b', 'b', 'b', 'a', 'a', 'a', 'c'] we get the output:
[('c', 1), ('b', 3), ('a', 3)]
using this I believe we solve the sorting by alphabet issue. if tuple at position n's second value is equal to the second value of tuple at positon n+1 we note the equality and go to our next if statement with those values. Because we start at position 0 we are sure to not skip any potential matches.
#set the n value for range 0, n to the number of tuple entries in the list.
for n in range(0,2):
if tuple[n][1]==tuple[n+1][1]:
print("there is an equality")
var1=str(tuple[n][0])
var2= str(tuple[n+1][0])
if var1 > var2:
print(var1, var2)
print("this is true")
# if tuple at position n's 1st value (alphabeticaly) is greater than tuple n+1's first value then we switch them.
tuple[n], tuple[n+1] = tuple[n+1], tuple[n]
print(tuple)
from initial list l with 3 "a"s and 3 "b"s we get the output:
[('c', 1), ('a', 3), ('b', 3)]
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 | Ayush Kumar Bhadani |
| Solution 2 | |
| Solution 3 |
