Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: use navigate without hook #8481

Closed
jkiss opened this issue Dec 14, 2021 · 16 comments
Closed

[Feature]: use navigate without hook #8481

jkiss opened this issue Dec 14, 2021 · 16 comments
Labels

Comments

@jkiss
Copy link

jkiss commented Dec 14, 2021

What is the new or updated feature that you are suggesting?

a static navigate function that can be used without hook, like:

import { navigate } from 'react-router-dom'

function notReactHook(){
    if(condition){
        navigate('a toute')
    }
}

Why should this feature be included?

I have a api.js file, it's not React Component, I want to navigate to login page when api(need login) request failed.

@jkiss jkiss added the feature label Dec 14, 2021
@elevensky

This comment has been minimized.

1 similar comment
@guozi007a

This comment has been minimized.

@timdorr
Copy link
Member

timdorr commented Dec 14, 2021

There is a new API for this:

import { createBrowserHistory } from 'history';
import { unstable_HistoryRouter as HistoryRouter } from 'react-router-dom';

let history = createBrowserHistory();

function App() {
  return (
    <HistoryRouter history={history}>
      // The rest of your app
    </HistoryRouter>
  );
}

history.push("/foo");

Use that history instance to navigate from outside React.

@goffioul
Copy link

The problem with the proposed solution is when your app is served with a non-empty basename. Because basename handling has been moved from history (up to Router), you need prepend the basename when using the history instance directly, while you don't when using useNavigate from react component. This assymmetry is confusing.

@Kamran95
Copy link

Your proposed solution doesn't work in redux store as route changes but components doesn't re render
the page remains same

APP.js
import "./App.css";
import Routes from "./Routes/router";

import {
unstable_HistoryRouter as HistoryRouter,
BrowserRouter,
} from "react-router-dom";
import { createBrowserHistory } from "history";

let history = createBrowserHistory();

function App() {
return (

);
}

export default App;

Redux Store actions
import { createBrowserHistory } from "history";
let history = createBrowserHistory();

export const Login = (data) => (dispatch) => {
console.log("Welocme to login Action");
public_url
.post("auth", data)
.then((res) => {
let data = {
userDetails: res.data.data,
token: res.headers["x-auth-token"],
};
dispatch(LoginSuccess(data));
history.push("welcome");

})
.catch((err) => {
if (err.response) {
const errors = err.response.data.errors;
dispatch(LoginFailed(errors));
}
});
};

Issue
route changes to localhost:3000/welcome but page remains same

@Kamran95
Copy link

Kindly solve this issue as i don't want to downgrade to V5 as i have implemented react-router V^ in most of the product

@goffioul
Copy link

@Kamran95 You're creating 2 history instances of history in the snippets you posted. You're supposed to create only one and use it in your app when you need it.

@Kamran95
Copy link

can you please provide example please

@Kamran95
Copy link

Kamran95 commented Dec 17, 2021

import "./App.css";

import Routes from "./Routes/router";
import {
unstable_HistoryRouter as HistoryRouter,
BrowserRouter,
} from "react-router-dom";
import { createBrowserHistory } from "history";

let history = createBrowserHistory();

function App() {
return (
<HistoryRouter history={history}> <Routes /> </HistoryRouter>
);
}
history.push("/welcome");

export default App;

this also doesn't work just for testinng

@Kamran95
Copy link

and you cannot use BrowserRouter while using HistoryRouter

@Kamran95
Copy link

Kamran95 commented Dec 17, 2021

@Kamran95 You're creating 2 history instances of history in the snippets you posted. You're supposed to create only one and use it in your app when you need it.

@goffioul please help me out it would help me alot

@goffioul
Copy link

What I mean is that you create a single history instance in a module and you import that module elsewhere in your app when you need to access the history.

History.js

import { createBrowserHistory } from "history";

export const history = createBrowserHistory();

App.js

import { unstable_HistoryRouter } from 'react-router-dom';
import { history } from './History';

function App() {
    return (
        <HistoryRouter history={history}>
            ...
        </HistoryRouter>
    );
}

Redux store

import { history } from './History';

export const Login = (data) => (dispatch) => {
    ...
    history.push("welcome");
    ...
};

@jkiss
Copy link
Author

jkiss commented Dec 17, 2021

I found a solution is below, don't need install history package, may it help:

History.js

const History = {
    navigate: null,
    push: (page, ...rest) => History.navigate(page, ...rest),
}

export default History

NavigateSetter.js

import { useNavigate } from 'react-router-dom'
import History from './History'

const NavigateSetter = () => {
    History.navigate = useNavigate()

    return null
};

export default NavigateSetter

App.js

import NavigateSetter from './NavigateSetter'

const App = () => {
    History.navigate = useNavigate()

    return <Router>
        <NavigateSetter />

        <Routes>
               <Route
                      path={config.route.user.path}
                      element={<User />} />
         </Routes>
                
     </Router>
};

export default App

AnyFiles.js

import History from '../../History'

if(!login){
  History.navigate('/login')
}

@undeletable
Copy link

Looks like there's out-of-the-box solution: https://reactrouter.com/en/main/fetch/redirect
I haven't tested it though

@Twiggeh
Copy link

Twiggeh commented May 18, 2023

Looks like there's out-of-the-box solution: https://reactrouter.com/en/main/fetch/redirect I haven't tested it though

This doesn't work all of the time unfortunately, came here exactly because it doesn't work for this use-case, I believe its for the new data-router.

@sunnylqm
Copy link

#9422 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants