skip to Main Content

I’m using useNavigate from react-router-dom to redirect users to different pages of website. I’m passing useNavigate as a prop to my Components so I can evaluate it later when user clicks on a button. all of my components are inside a BrowserRouter Component from react-router-dom but it still throws an error. here is my App component:

function App() {
  const navigate = useNavigate();
    return (
        <BrowserRouter>
            <main dir="rtl" lang="fa">
                <header>
                    <NavBar />
                </header>
                <Routes>
                    <Route index element={<ElectricalPanel onClick={() => navigate("efuse/")} />} />
                    <Route path="duct/" element={<Duct onClick={() => navigate("wiresho/")} />} />
                    <Route path="efuse/" element={<EFuse onClick={() => navigate("duct/")} />} />
                    <Route path="rail/" element={<Rail onClick={() => navigate("shemsh/")} />} />
                    <Route path="screw/" element={<Screw onClick={() => navigate("/")} />} />
                    <Route path="shemsh/" element={<Shemsh onClick={() => navigate("terminal/")} />} />
                    <Route path="slamp/" element={<SignalLamp onClick={() => navigate("screw/")} />} />
                    <Route path="terminal/" element={<Terminal onClick={() => navigate("slamp/")} />} />
                    <Route path="wiresho/" element={<WireSho onClick={() => navigate("rail/")} />} />
                </Routes>
            </main>
        </BrowserRouter>
    );
}

This is one of my components(all components have same/similar handleSubmit functions):

const Screw = ({onClick}) => {
    const [count, setCount] = useState(null);
    const handleSubmit = () => {
        onClick();
    }
    return (
        <div>
            <h1>پیچ</h1>
            <div className="fuse-container">
                <div
                    className="fuse-option"
                    onChange={(e) => setCount(parseInt(e.target.value))}
                >
                    <label htmlFor="count">تعداد بسته پیچ را وارد کنید:</label>
                    <input type="number" id="count" />
                </div>
            </div>
            <div>{count > 0 && <button onClick={handleSubmit}>تایید</button>}</div>
        </div>
    );
};

As you can see I have some Routes inside a Routes component inside a BrowserRouter Component. But it still says my navigate is not inside BrowserRouter.

2

Answers


  1. It’s actually the case because you try to call useNavigate inside App component but this component isn’t wrapped with BrowserRouter. It should be wrapoed outside. Wrap your App Component with BrowserRouter in your main.js or index.js.

    Like this:

    import * as React from "react";
    import * as ReactDOM from "react-dom/client";
    import { BrowserRouter } from "react-router-dom";
    
    import "./index.css";
    import App from "./App";
    
    ReactDOM.createRoot(document.getElementById("root")!).render(
      <React.StrictMode>
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </React.StrictMode>
    );
    

    Solution 2.
    You can put pathname string as prop instead of onClick handler and navigate users in nested components. In that case you don’t need useNavigate inside your App component.

    const Screw = ({pathname}) => {
        const navigate = useNavigate();
        const [count, setCount] = useState(null);
        const handleSubmit = () => {
            navigate(pathname);
        }
        return 
    
    (
            <div>
        
    
        <h1>پیچ</h1>
                <div className="fuse-container">
                    <div
                        className="fuse-option"
                        onChange={(e) => setCount(parseInt(e.target.value))}
                    >
                        <label htmlFor="count">تعداد بسته پیچ را وارد کنید:</label>
                        <input type="number" id="count" />
                    </div>
                </div>
                <div>{count > 0 && <button onClick={handleSubmit}>تایید</button>}</div>
            </div>
        );
    };
    

    App.jsx

    function App() {
      
        return (
            <BrowserRouter>
                <main dir="rtl" lang="fa">
                    <header>
                        <NavBar />
                    </header>
                    <Routes>
                        <Route index element={<ElectricalPanel onClick={() => navigate("efuse/")} />} />
                        <Route path="duct/" element={<Duct onClick={() => navigate("wiresho/")} />} />
                        <Route path="efuse/" element={<EFuse onClick={() => navigate("duct/")} />} />
                        <Route path="rail/" element={<Rail onClick={() => navigate("shemsh/")} />} />
                        <Route path="screw/" element={<Screw onClick={() => navigate("/")} />} />
                        <Route path="shemsh/" element={<Shemsh onClick={() => navigate("terminal/")} />} />
                        <Route path="slamp/" element={<SignalLamp onClick={() => navigate("screw/")} />} />
                        <Route path="terminal/" element={<Terminal onClick={() => navigate("slamp/")} />} />
                        <Route path="wiresho/" element={<WireSho onClick={() => navigate("rail/")} />} />
                    </Routes>
                </main>
            </BrowserRouter>
        );
    }
    
    Login or Signup to reply.
  2. The error you’re encountering is likely because you’re calling useNavigate() outside of the BrowserRouter. The useNavigate hook must be used within a component that’s rendered inside a BrowserRouter (or any other router like HashRouter).

    In your current App component, you’re using useNavigate directly in the root component before the BrowserRouter is rendered, which is causing the error.

    To fix this, you should call useNavigate inside your components or pass the navigate function down to your components through props only after the BrowserRouter is rendered.

     function App() {
        return (
            <BrowserRouter>
                <main dir="rtl" lang="fa">
                    <header>
                        <NavBar />
                    </header>
                    <Routes>
                        <Route index element={<ElectricalPanel />} />
                        <Route path="duct/" element={<Duct />} />
                        <Route path="efuse/" element={<EFuse />} />
                        <Route path="rail/" element={<Rail />} />
                        <Route path="screw/" element={<Screw />} />
                        ...
                    </Routes>
                </main>
            </BrowserRouter>
        );
    }
    

    here is your Screw component for ex

    const Screw = () => {
    const [count, setCount] = useState(null);
    const navigate = useNavigate();
    
    const handleSubmit = () => {
        navigate("/");
    };
    return (
        <div>
            <h1>پیچ</h1>
            <div className="fuse-container">
                <div
                    className="fuse-option"
                    onChange={(e) => setCount(parseInt(e.target.value))}
                >
                    <label htmlFor="count">تعداد بسته پیچ را وارد کنید:</label>
                    <input type="number" id="count" />
                </div>
            </div>
            <div>{count > 0 && <button onClick={handleSubmit}>button</button>}</div>
        </div>
    );
    

    };

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search