OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

How to resolve the error: useNavigate() may be used only in the context of a <Router> component?

  • Thread starter Thread starter mightycode Newton
  • Start date Start date
M

mightycode Newton

Guest
I am using react typescript. And I have a userContext for register users and login.

But if I try to wrap the context in the _app.tsx file. Then I get this error:

Code:
error - Error: useNavigate() may be used only in the context of a <Router> component.

So this is part of the UserProvider:

Code:
/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
import { createContext, useEffect, useState } from "react";
import { loginAPI, registerAPI } from "../services/AuthService";

import React from "react";
import { UserProfile } from "../models/User";
import axios from "axios";
import { toast } from "react-toastify";
import { useNavigate } from "react-router-dom";

type UserContextType = {
  user: UserProfile | null;
  token: string | null;  
  loginUser: (username: string, password: string) => void;  
  isLoggedIn: () => boolean;
};

type Props = { children: React.ReactNode };

const UserContext = createContext<UserContextType>({} as UserContextType);

export const UserProvider = ({ children }: Props) => {
  const navigate = useNavigate();
  const [token, setToken] = useState<string | null>(null);
  const [user, setUser] = useState<UserProfile | null>(null);
  const [isReady, setIsReady] = useState(false);

  useEffect(() => {
    const user = localStorage.getItem("user");
    const token = localStorage.getItem("token");
    if (user && token) {
      setUser(JSON.parse(user));
      setToken(token);
      axios.defaults.headers.common["Authorization"] = "Bearer " + token;
    }
    setIsReady(true);
  }, []);



  const loginUser = async (username: string, password: string) => {
    await loginAPI(username, password)
      .then((res) => {
        if (res) {
          localStorage.setItem("token", res?.data.token);
          const userObj = {
            username: res?.data.username,
            email: res?.data.email,
          };
          localStorage.setItem("user", JSON.stringify(userObj));
          setToken(res?.data.token!);
          setUser(userObj!);
          toast.success("Login Success!");
          navigate("/");
        }
      })
      .catch((e) => toast.warning("Server error occured"));
  };

  const isLoggedIn = () => {
    return !!user;
  };

  return (
    <UserContext.Provider
      value={{ loginUser, user, token, isLoggedIn  }}
    >
      {isReady ? children : null}
    </UserContext.Provider>
  );
};

export const useAuth = () => React.useContext(UserContext);

And the error apears on this line:

Code:
 const navigate = useNavigate();

And then I try to wrap the UserProvider in the _app.tsx file:

Code:
/* eslint-disable lines-around-comment */
// ** React Perfect Scrollbar Style
import 'react-perfect-scrollbar/dist/css/styles.css'
// ** Global css styles
import '../../styles/globals.css'
import "react-toastify/dist/ReactToastify.css"

// ** Contexts
import { SettingsConsumer, SettingsProvider } from 'src/context/settingsContext'

import type { AppProps } from 'next/app'
// ** Emotion Imports
import { CacheProvider } from '@emotion/react'
import type { EmotionCache } from '@emotion/cache'
// ** Next Imports
import Head from 'next/head'
// ** Loader Import
import NProgress from 'nprogress'
import type { NextPage } from 'next'
import { Router } from 'next/router'
import ThemeComponent from 'src/@core/theme/ThemeComponent'
// ** Component Imports
import UserLayout from 'src/layouts/UserLayout'
import { UserProvider } from 'src/context/useAuth'
// ** Utils Imports
import { createEmotionCache } from 'src/@core/utils/create-emotion-cache'
// ** Config Imports
import themeConfig from 'src/configs/themeConfig'

// ** Extend App Props with Emotion
type ExtendedAppProps = AppProps & {
  Component: NextPage
  emotionCache: EmotionCache
}

const clientSideEmotionCache = createEmotionCache()

// ** Pace Loader
if (themeConfig.routingLoader) {
  Router.events.on('routeChangeStart', () => {
    NProgress.start()
  })
  Router.events.on('routeChangeError', () => {
    NProgress.done()
  })
  Router.events.on('routeChangeComplete', () => {
    NProgress.done()
  })
}

// ** Configure JSS & ClassName
const App = (props: ExtendedAppProps) => {
  const { Component, emotionCache = clientSideEmotionCache, pageProps } = props

  // Variables
  const getLayout = Component.getLayout ?? (page => <UserLayout>{page}</UserLayout>)

  return (
    <>
  <UserProvider>
    <CacheProvider value={emotionCache}>
      <Head>
        <title>{`${themeConfig.templateName} - Material Design React Admin Template`}</title>
        <meta
          name='description'
          content={`${themeConfig.templateName} – Material Design React Admin Dashboard Template – is the most developer friendly & highly customizable Admin Dashboard Template based on MUI v5.`}
        />
        <meta name='keywords' content='Material Design, MUI, Admin Template, React Admin Template' />
        <meta name='viewport' content='initial-scale=1, width=device-width' />
      </Head>

      <SettingsProvider>
        <SettingsConsumer>
          {({ settings }) => {
              return <><ThemeComponent settings={settings}>{getLayout(<Component {...pageProps} />)}</ThemeComponent></>
          }}
          </SettingsConsumer>

      </SettingsProvider>
        </CacheProvider>
  </UserProvider>

      </>

  )
}
export default App

But if I try this I get the error:

Code:
Error: useNavigate() may be used only in the context of a <Router> component.

And I checked the different versions. And it returned the same versions:

Code:
yarn list v1.22.19
warning Filtering by arguments is deprecated. Please use the pattern option instead.
├─ [email protected]
└─ [email protected]

Question: how to resolve this error?

<p>I am using react typescript. And I have a userContext for register users and login.</p>
<p>But if I try to wrap the context in the _app.tsx file. Then I get this error:</p>
<pre><code>error - Error: useNavigate() may be used only in the context of a <Router> component.
</code></pre>
<p>So this is part of the UserProvider:</p>
<pre><code>/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
import { createContext, useEffect, useState } from "react";
import { loginAPI, registerAPI } from "../services/AuthService";

import React from "react";
import { UserProfile } from "../models/User";
import axios from "axios";
import { toast } from "react-toastify";
import { useNavigate } from "react-router-dom";

type UserContextType = {
user: UserProfile | null;
token: string | null;
loginUser: (username: string, password: string) => void;
isLoggedIn: () => boolean;
};

type Props = { children: React.ReactNode };

const UserContext = createContext<UserContextType>({} as UserContextType);

export const UserProvider = ({ children }: Props) => {
const navigate = useNavigate();
const [token, setToken] = useState<string | null>(null);
const [user, setUser] = useState<UserProfile | null>(null);
const [isReady, setIsReady] = useState(false);

useEffect(() => {
const user = localStorage.getItem("user");
const token = localStorage.getItem("token");
if (user && token) {
setUser(JSON.parse(user));
setToken(token);
axios.defaults.headers.common["Authorization"] = "Bearer " + token;
}
setIsReady(true);
}, []);



const loginUser = async (username: string, password: string) => {
await loginAPI(username, password)
.then((res) => {
if (res) {
localStorage.setItem("token", res?.data.token);
const userObj = {
username: res?.data.username,
email: res?.data.email,
};
localStorage.setItem("user", JSON.stringify(userObj));
setToken(res?.data.token!);
setUser(userObj!);
toast.success("Login Success!");
navigate("/");
}
})
.catch((e) => toast.warning("Server error occured"));
};

const isLoggedIn = () => {
return !!user;
};

return (
<UserContext.Provider
value={{ loginUser, user, token, isLoggedIn }}
>
{isReady ? children : null}
</UserContext.Provider>
);
};

export const useAuth = () => React.useContext(UserContext);
</code></pre>
<p>And the error apears on this line:</p>
<pre><code> const navigate = useNavigate();
</code></pre>
<p>And then I try to wrap the UserProvider in the _app.tsx file:</p>
<pre><code>/* eslint-disable lines-around-comment */
// ** React Perfect Scrollbar Style
import 'react-perfect-scrollbar/dist/css/styles.css'
// ** Global css styles
import '../../styles/globals.css'
import "react-toastify/dist/ReactToastify.css"

// ** Contexts
import { SettingsConsumer, SettingsProvider } from 'src/context/settingsContext'

import type { AppProps } from 'next/app'
// ** Emotion Imports
import { CacheProvider } from '@emotion/react'
import type { EmotionCache } from '@emotion/cache'
// ** Next Imports
import Head from 'next/head'
// ** Loader Import
import NProgress from 'nprogress'
import type { NextPage } from 'next'
import { Router } from 'next/router'
import ThemeComponent from 'src/@core/theme/ThemeComponent'
// ** Component Imports
import UserLayout from 'src/layouts/UserLayout'
import { UserProvider } from 'src/context/useAuth'
// ** Utils Imports
import { createEmotionCache } from 'src/@core/utils/create-emotion-cache'
// ** Config Imports
import themeConfig from 'src/configs/themeConfig'

// ** Extend App Props with Emotion
type ExtendedAppProps = AppProps & {
Component: NextPage
emotionCache: EmotionCache
}

const clientSideEmotionCache = createEmotionCache()

// ** Pace Loader
if (themeConfig.routingLoader) {
Router.events.on('routeChangeStart', () => {
NProgress.start()
})
Router.events.on('routeChangeError', () => {
NProgress.done()
})
Router.events.on('routeChangeComplete', () => {
NProgress.done()
})
}

// ** Configure JSS & ClassName
const App = (props: ExtendedAppProps) => {
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props

// Variables
const getLayout = Component.getLayout ?? (page => <UserLayout>{page}</UserLayout>)

return (
<>
<UserProvider>
<CacheProvider value={emotionCache}>
<Head>
<title>{`${themeConfig.templateName} - Material Design React Admin Template`}</title>
<meta
name='description'
content={`${themeConfig.templateName} – Material Design React Admin Dashboard Template – is the most developer friendly & highly customizable Admin Dashboard Template based on MUI v5.`}
/>
<meta name='keywords' content='Material Design, MUI, Admin Template, React Admin Template' />
<meta name='viewport' content='initial-scale=1, width=device-width' />
</Head>

<SettingsProvider>
<SettingsConsumer>
{({ settings }) => {
return <><ThemeComponent settings={settings}>{getLayout(<Component {...pageProps} />)}</ThemeComponent></>
}}
</SettingsConsumer>

</SettingsProvider>
</CacheProvider>
</UserProvider>

</>

)
}
export default App
</code></pre>
<p>But if I try this I get the error:</p>
<pre><code>Error: useNavigate() may be used only in the context of a <Router> component.
</code></pre>
<p>And I checked the different versions. And it returned the same versions:</p>
<pre><code>yarn list v1.22.19
warning Filtering by arguments is deprecated. Please use the pattern option instead.
├─ [email protected]
└─ [email protected]
</code></pre>
<p>Question: how to resolve this error?</p>
 

Latest posts

Top