头图

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.

usenavigate-may-be-used-only-in-the-context-of-router.png

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.


chuck
300 声望41 粉丝