The text starts here~
Overview
When we try to use the useNavigate
hook outside of React Router's Router context, the "useNavigate() may be used only in the context of a Router component" warning is generated. To solve this problem, only use the useNavigate
hook in the context of the Router.
Below is an example of wrapping a React application into a Router in the index.js
file.
// index.js
import {createRoot} from 'react-dom/client';
import App from './App';
import {BrowserRouter as Router} from 'react-router-dom';
const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
// 👇️ wrap App in Router
root.render(
<Router>
<App />
</Router>
);
useNavigate
Now, you can use the useNavigate
hook in the App.js file.
// App.js
import React from 'react';
import {
useNavigate,
} from 'react-router-dom';
export default function App() {
const navigate = useNavigate();
const handleClick = () => {
// 👇️ navigate programmatically
navigate('/about');
};
return (
<div>
<button onClick={handleClick}>Navigate to About</button>
</div>
);
}
The error occurs because the useNavigate
hook uses the context provided by the Router component, so it must be nested inside the Router.
The best place to wrap your React application with the Router component is in your index.js
file, because that's the entry point of your React application.
Once your entire application is wrapped by the Router component, you can use the hooks provided by react router in the component anytime and anywhere.
Jest
If you encounter errors when using the Jest testing library, the solution is the same. You have to wrap the component using the useNavigate
hook in a Router.
// App.test.js
import {render} from '@testing-library/react';
import App from './App';
import {BrowserRouter as Router} from 'react-router-dom';
// 👇️ wrap component that uses useNavigate in Router
test('renders react component', async () => {
render(
<Router>
<App />
</Router>,
);
// your tests...
});
useNavigate
hook returns a function that allows us to programmatically do routing jumps, for example after a form submit.
The arguments we pass to the navigate
function are the same as the to
<Link to="/about">
component.
replace
If you want to use the equivalent of history.replace()
, pass a configuration parameter to the navigate
function.
// App.js
import {useNavigate} from 'react-router-dom';
export default function App() {
const navigate = useNavigate();
const handleClick = () => {
// 👇️ replace set to true
navigate('/about', {replace: true});
};
return (
<div>
<button onClick={handleClick}>Navigate to About</button>
</div>
);
}
When the value of the replace
property is set to true
in the configuration object, the current entry in the browser history stack is replaced by the new entry.
In other words, navigating to a new route this way does not push a new entry in the browser history stack. So if the user hits the back button, it doesn't navigate to the previous page.
This is useful. For example, when the user is logged in, you don't want the user to be able to click the back button and go back to the login page again. Or, if you have a route that redirects to another page, you don't want the user to click the back button and redirect again.
You can also call navigate
function with a numeric value to achieve the effect of rewinding from the history stack. For example, navigate(-1)
is equivalent to pressing the back button.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。