I’m developing a React application and I’m encountering an error when using the useLocation
hook from the react-router-dom
library. The error message I receive is:
Error: useLocation() may be used only in the context of a component.
Here is the relevant part of my App.js
file:
import { useEffect, useState } from 'react'
import { createBrowserRouter, RouterProvider, useLocation } from 'react-router-dom'
// Components
import Navigation from './components/Navigation'
import Section from './components/Section'
import Product from './components/Product'
import Login from './components/Login'
// ABIs
import Dappazon from './abis/Dappazon.json'
// Config
import config from './config.json'
const ethers = require('ethers')
function App() {
const [provider, setProvider] = useState(null)
const [dappazon, setDappazon] = useState(null)
const [account, setAccount] = useState(null)
const [electronics, setElectronics] = useState(null)
const [clothing, setClothing] = useState(null)
const [toys, setToys] = useState(null)
const [item, setItem] = useState(null)
const [toggle, setToggle] = useState(false)
const location = useLocation()
const togglePop = (item) => {
setItem(item)
toggle ? setToggle(false) : setToggle(true)
}
const loadBlockchainData = async () => {
const provider = new ethers.BrowserProvider(window.ethereum)
setProvider(provider)
const network = await provider.getNetwork()
const dappazon = new ethers.Contract(config[network.chainId].dappazon.address, Dappazon, provider)
setDappazon(dappazon)
const items = []
for (var i = 0; i < 9; i++) {
const item = await dappazon.items(i + 1)
items.push(item)
}
const electronics = items.filter((item) => item.category === 'electronics')
const clothing = items.filter((item) => item.category === 'clothing')
const toys = items.filter((item) => item.category === 'toys')
setElectronics(electronics)
setClothing(clothing)
setToys(toys)
}
useEffect(() => {
loadBlockchainData()
}, [])
const router = createBrowserRouter([
{
path: "/login",
element: <><Navigation account={account} setAccount={setAccount} /><Login /></>
},
{
path: "/",
element: <><Navigation account={account} setAccount={setAccount} /></>
},
{
path: "/Clothing&Jewelry",
element: <><Navigation account={account} setAccount={setAccount} /><Section title={"Clothing & Jewelry"} items={clothing} togglePop={togglePop} /></>
},
{
path: "/Electronics&Gadgets",
element: <><Navigation account={account} setAccount={setAccount} /><Section title={"Electronics & Gadgets"} items={electronics} togglePop={togglePop} /></>
},
{
path: "/Toys&Gaming",
element: <><Navigation account={account} setAccount={setAccount} /><Section title={"Toys & Gaming"} items={toys} togglePop={togglePop} /></>
},
])
return (
<>
<div>
{/* <Navigation account={account} setAccount={setAccount} /> */}
<RouterProvider router={router} />
{electronics && clothing && toys && location.pathname === '/' && (
<>
<h2>Dappazon Best Sellers</h2>
<Section title={"Clothing & Jewelry"} items={clothing} togglePop={togglePop} />
<Section title={"Electronics & Gadgets"} items={electronics} togglePop={togglePop} />
<Section title={"Toys & Gaming"} items={toys} togglePop={togglePop} />
</>
)}
{toggle && (
<Product item={item} provider={provider} account={account} dappazon={dappazon} togglePop={togglePop} />
)}
</div>
</>
);
}
export default App;
I have already ensured that RouterProvider wraps the component that uses useLocation, but the error persists. The useLocation hook is being used within the App component which is wrapped inside the RouterProvider as shown above.
What could be causing this issue and how can I resolve it?
2
Answers
In your
App
component,useLocation
is being called directly within theApp
function. However,RouterProvider
is supposed to wrap the entire component tree where theuseLocation
hook is used. To fix the error, move theuseLocation
logic into a separate component, then wrap the component tree inside RouterProvider:Reason:
You are getting this error because useLocation can be used only in the context of a component). In your case, that App is not directly inside a context.
How to fix it?
You must ensure that the useLocation hook is used inside a component that is within the router context. For this you need to refactor your code in a way that useLocation is called within a component that is rendered by the router.
Create a Seprate Component for handling location related logic. and add that Component as default route with index and perform location related task there.