skip to Main Content

I have an web application with ReactTS. I use react-router library for navigation and I need to navigate user to registration page on Registration button click programmatically.

I found several ways to do that programmatically in react-router:

  1. with useNavigate hook – it can be used only inside components.
  2. with redirect function – it’s work only for loaders.

I use function components with hooks, but do not want to keep a lot of logic inside component. I want to move that logic to services layer. Now I’m searching for way to navigate programmatically without hooks.

That’s my code:

import { redirect, useNavigate } from 'react-router-dom';
import { AUTHORIZATION_REGISTRATION_MAILBOX } from '../../../constants/routes';

export const LogInComponent = () => {
  const navigate = useNavigate();

  const goToRegistration = () => {
    redirect(AUTHORIZATION_REGISTRATION_MAILBOX); // it's not working
    navigate(AUTHORIZATION_REGISTRATION_MAILBOX); // it's working but only inside component
  }

  return (
    <div>
      <button className='enter-button' onClick={goToRegistration}>
        Registration
      </button>
    </div>
  );
};

UPD 1

I’m looking for solution like that:

  1. Component uses service
import { registrateUser } from './registrationService'

export const RegistrationComponent = () => {
  
  const registrate = () => {
    registrateUser();
  }

  return (
    <div>
      <button onClick={registrate}>
        Registrate
      </button>
    </div>
  );
}
  1. Service makes some logic and redirect user by navigation service
import { redirectTo } from './navigationService'

export const registrateUser = () => {
  
  // makes some logic

  redirectTo(/*some path*/);
}
  1. Navigation service should redirect user
export const registrateUser = (path: string) => {
  window.location.href = path; // as example
}

That solution with window.location.href is working, but it clears state values (context values and store values). So it’s not good decision.

4

Answers


  1. I have used the useNavigate hook inside the shared service function, it works for me. Kindly try the below example.

    App.tsx

    import React from "react";
    import { navigateTo } from "./sharedService";
    
    const App = () => {
        navigateTo('/path');
        return (
            <></>
        );
    };
    
    export default App;
    

    SharedService.ts

    import { useNavigate } from "react-router-dom";
    
    export const navigateTo = (redirectTo: string) => {
        const navigate = useNavigate();
        navigate(redirectTo);
    };
    
    Login or Signup to reply.
  2. The version using the useNavigate hook and navigate function is the correct one of the options you’ve presented.

    import { useNavigate } from 'react-router-dom';
    import { AUTHORIZATION_REGISTRATION_MAILBOX } from '../../../constants/routes';
    
    export const LogInComponent = () => {
      const navigate = useNavigate();
    
      const goToRegistration = () => {
        navigate(AUTHORIZATION_REGISTRATION_MAILBOX);
      }
    
      return (
        <div>
          <button className='enter-button' onClick={goToRegistration}>
            Registration
          </button>
        </div>
      );
    };
    

    If you are trying to extract this logic into a reusable unit then you’ll likely need to create a custom hook such that the useNavigate hook is validly called. Custom React hooks are what allow for code reuse.

    Example:

    import { useNavigate } from 'react-router-dom';
    import { AUTHORIZATION_REGISTRATION_MAILBOX } from '../../../constants/routes';
    
    export const useRegistrateUser = () => {
      const navigate = useNavigate();
    
      return (/* args? */) => {
        ... other business logic ...
    
        navigate(AUTHORIZATION_REGISTRATION_MAILBOX);
      };
    };
    
    import { useRegistrateUser } from './registrationService'
    
    export const RegistrationComponent = () => {
      const { registrateUser } = useRegistrateUser();
    
      const registrate = () => {
        registrateUser(); // <-- pass any args, if necessary
      }
    
      return (
        <div>
          <button onClick={registrate}>
            Registrate
          </button>
        </div>
      );
    };
    
    Login or Signup to reply.
  3. beacause react-router’s ability is available in a Provider(Router), so you can only navigate in react-router with compoent.

    you can still change window.location.pathname directly, but it will let browser reload, so it can’t keep app state anymore

    Login or Signup to reply.
  4. const LoginPage = (props: LoginPageProps) => {
        const location = useLocation();
    
        return <Navigate to={'your path'} state={{ from: location }} replace />
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search