My code currently is this and I'm trying to add this button that goes back to the previous page using react-router-dom but I get an error saying 'useNavigate() may be used only in the context of a component.' and also all the components on my website disappears.
function App() {
const navigate = useNavigate();
return (
<BrowserRouter>
<div>
<button onClick={() => navigate(-1)}>go back</button>
<Nav/>
<Routes>
<Route exact path="/" element={<Home/>}/>
<Route exact path="/home" element={<Home/>}/>
<Route exact path="/upcoming/:user" element={<Upcoming/>}/>
<Route exact path="/record/:user" element={<Record/>}/>
<Route path="*" element={<NotFound/>}/>
</Routes>
</div>
</BrowserRouter>
);
}
This is the error I got in console
This error throws in useNavigate. useInRouterContext will check if the component(which uses useNavigate
hook) is a descendant of a <Router>
.
Here's the source code to explain why you can't use useNavigate
, useLocation
outside of the Router component:
useNavigate
uses useLocation
underly, useLocation
will get the location from LocationContext. If you want to get the react context, you should render the component as the descendant of a context provider.
Router
component use the LocationContext.Provider and NavigationContext.Provider. That's why you need to render the component as the children, so that useNavigate
hook can get the context data from NavigationContext
and LocationContext
providers.
Your environment is browser, so you need to use BrowserRouter
. BrowserRouter
is built based on Router
.
Refactor to this:
App.jsx
:
function App() {
const navigate = useNavigate();
return (
<div>
<button onClick={() => navigate(-1)}>go back</button>
<Nav/>
<Routes>
<Route exact path="/" element={<Home/>}/>
<Route exact path="/home" element={<Home/>}/>
<Route exact path="/upcoming/:user" element={<Upcoming/>}/>
<Route exact path="/record/:user" element={<Record/>}/>
<Route path="*" element={<NotFound/>}/>
</Routes>
</div>
);
}
index.jsx
:
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
ReactDOM.render(
<BrowserRouter>
<App/>
</BrowserRouter>,
document.getElementById('root')
)
You are using hook outside BrowserRouter provider. that's why you are getting errors. Refactor you component like below to solve this issue
function Root() {
const navigate = useNavigate();
return (
<div>
<button onClick={() => navigate(-1)}>go back</button>
<Nav />
<Routes>
<Route exact path="/" element={<Home />} />
<Route exact path="/home" element={<Home />} />
<Route exact path="/upcoming/:user" element={<Upcoming />} />
<Route exact path="/record/:user" element={<Record />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
);
}
function App() {
return (
<BrowserRouter>
<Root />
</BrowserRouter>
);
}
I had this same issue but with testing a component that has the hook useNavigate on it. Solved it by wrapping my component in a route with routes and browser router. Hope this helps others with the same error.
let container = null;
beforeEach(() => {
container = document.createElement("div");
document.body.appendChild(container);
});
afterEach(() => {
// cleanup on exiting
unmountComponentAtNode(container);
container.remove();
container = null;
});
test('finds qualified insurrance policies', () => {
act(() => {
render(
<BrowserRouter>
<Routes>
<Route path="*" element= {<QuaifiedPolicies policyTypes={false} />}/>
</Routes>
</BrowserRouter>
, container);
});
expect(screen.getByLabelText('some text'))
});