History.push works on BrowserRouter but not Router - javascript

So I'm trying to use history.push('/path') in my components. My set up looks like this:
App.js
import { Router, Switch, Route } from 'react-router-dom';
// History
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
function App() {
return (
<Router history={history}>
<Switch>
<Route path='/' exact render={(props) => <Homepage />} />
<Route path='/search' render={(props) => <SecondComponent />} />
</Switch>
</Router>
);
}
export default App;
SecondComponent.js
import React from 'react';
import { withRouter } from "react-router-dom";
const SecondComponent = ({ history }) => {
const myFunction = () => {
history.push('/search');
};
return (
<button onClick={() => myFunction}>stuff</button>
);
}
export default withRouter(SecondComponent);
The problem is that when I click the button the URL changes but the component doesn't render. The thing is if I replace Router in app.js with BrowserRouter it works fine but I get a warning: <BrowserRouter> ignores the history prop. To use a custom history, use import { Router } instead of import { BrowserRouter as Router }.

react-router 5x is compatible with history 4x. Check the history version, and if higher than 4x, try downgrading to 4x version, and it should work fine with Router

Related

Question about PrivateRoutes and to get navigated back to login page

Hi I need help getting my code to work so that when I try to log back in I won't be able to view the dashboard since I logged out. Right now its giving me a blank screen in my project and I think its because privateroute isn't a thing anymore? Not sure. This is my code in PrivateRoute.js:
import React, { Component } from 'react';
import { Route, Navigate } from 'react-router-dom';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
const PrivateRoute = ({ component: Component, auth: { isAuthenticated, loading },
...rest }) => (
<Route {...rest} render={props => !isAuthenticated && !loading ? (<Navigate to='/login' />) : (<Component {...props} />)} />
)
PrivateRoute.propTypes = {
auth: PropTypes.object.isRequired
};
const mapStatetoProps = state => ({
auth: state.auth
});
export default connect(mapStatetoProps)(PrivateRoute);
This is the code for the app.js:
import React, { Fragment, useEffect } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Navbar from './components/layout/Navbar';
import Landing from './components/layout/Landing';
import Register from './components/auth/Register';
import Login from './components/auth/Login';
import Alert from './components/layout/Alert';
import Dashboard from './components/dashboard/Dashboard';
import PrivateRoute from './components/routing/PrivateRoute';
// Redux
import { Provider } from 'react-redux';
import store from './store';
import { loadUser } from './actions/auth';
import setAuthToken from './utils/setAuthToken';
import './App.css';
if (localStorage.token) {
setAuthToken(localStorage.token);
}
const App = () => {
useEffect(() => {
store.dispatch(loadUser());
}, []);
return (
<Provider store={store}>
<Router>
<Fragment>
<Navbar />
<Routes>
<Route exact path='/' element={<Landing/>} />
</Routes>
<section className="container">
<Alert />
<Routes>
<Route exact path='/Register' element={<Register/>} />
<Route exact path='/Login' element={<Login/>} />
<PrivateRoute exact path='/dashboard' element={Dashboard} />
</Routes>
</section>
</Fragment>
</Router>
</Provider>
)};
export default App;
Please Help!
there is a recommended Protected Route implementation in the v6 react router docs you can follow.
DOCS IMPLEMENTATION
Your issue:
<Route {...rest} render={props => !isAuthenticated && !loading ?
(<Navigate to='/login' />) : (<Component {...props} />)} />
This Route is not up to date with v6, which I assume you are using, you need to update it.
Exact is also not supported anymore, there is no point in including it in your routes.
If you are not using v6 please update your post and include your react-router version.

Redirect to external link from React app using react-router-dom

What I want is when entering the '/' path, it renders the homepage (App.js), and I create a special link to redirect to an external page
import React from 'react';
import { Routes, Route } from 'react-router-dom';
import App from './App';
const Home = () => {
return (
<Routes>
<Route path="/" element={<App />} />
<Route path="/g" element={() => window.location.replace('https://google.com')} />
</Routes>
)
}
export default Home;
Result:
http://localhost:3004/ doesn't load the homepage and shows a blank
page instead
http://localhost:3004/g doesn't redirect, shows a blank page as above
So I tried to ditch the router and render the App directly, it's still working
import React from 'react';
import { Routes, Route } from 'react-router-dom';
import App from './App';
const Home = () => {
return (
<App />
)
}
export default Home;
What did I do wrong?
The issue is that your Route still needs to have a JSX element as the element prop. So just make a function that has your window.location.replace on it.
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="g" element={<Redirect />} />
</Routes>
</BrowserRouter>
);
}
function Home() {
return 'Home';
}
function Redirect() {
window.location.replace('https://google.com');
}

My react route is redirecting to localhost:3000 and not the page it should redirect to

I have 2 components both are exactly the same. one is redirected to when I click on a Navlink inside of my navbar that I created using react-bootstrap. The other component that is exactly the same just redirects to localhost:3000 and not "./member" when I click on the html button that should redirect to that component. Please help me.
the html button and the function to redirect look like
import {Link, Route, withRouter, useHistory} from 'react-router-dom'
const Posts = (props) => {
const dispatch = useDispatch();
const history = useHistory();
const getProfile = async (member) => {
// const addr = dispatch({ type: 'ADD_MEMBER', response: member })
console.log(member)
history.push('/member')
}
return (
<div>
<button onClick={() => getProfile(p.publisher)}>Profile</button>
</div>
)
}
export default withRouter(Posts);
The routes.js looks like
const Routes = (props) => {
return (
<Switch>
<Route path="/member" exact component={Member} />
</Switch>
)
}
export default Routes
The component that I am trying to redirect to is exactly the same as one that is redirected to and working when I click on it from the navlink. I have downgraded to history 4.10.1
My index.js is
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Router, Route } from 'react-router-dom';
import * as history from 'history';
import * as serviceWorker from './serviceWorker';
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import rootReducer from './reducers'
const store = createStore(rootReducer)
const userHistory = history.createBrowserHistory();
ReactDOM.render(
<Provider store = {store}>
<Router history={userHistory}>
<BrowserRouter>
<Route component={App} />
</BrowserRouter>
</Router>
</Provider>,
document.getElementById('root'));
serviceWorker.unregister();
When I wrap the app route in the url goes to ./member but it does not load.
<Switch>
<Route path="/" exact component={app} />
<Route path="/member" component={Member} />
</Switch>
<button onClick={() => history.push(`/${p.publisher}`)}>Profile</button>

TypeError: Cannot read property 'params' of undefined at App React Router

Whenever I console log props.match.params, I get an error:
TypeError: Cannot read property 'params' of undefined at App. I'm not sure this is relevant, but even if I console.log(props) I get four empty arrays.
Here is all the relevant code:
Home.js
import React from "react";
import App from "./App";
import { render } from "react-dom";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
Redirect,
} from "react-router-dom";
const Home = () => {
return (
<div>
<Router>
<Route exact path="/">
<App />
</Route>
<Route path="/:roomCode" component={App} />
</Router>
</div>
);
};
export default Home;
App.js (only the relevant part)
const App = (props) => {
console.log(props.match.params);
};
export default App;
const appDiv = document.getElementById("app");
render(<App />, appDiv);
I have been trying to figure this out for the past two days. Nothing works. Also, history.push also doesn't work, returns a very similar error. I have a feeling react-router-dom is broken in my project.
Help is much appreciated.
Edit:
Here is the codesandbox: https://codesandbox.io/s/reverent-microservice-iosu2?file=/src/App.js
Your Home Component is the root of all your components so it needs to be pass to render function not your App which is a descendent of Home.
after that change you need to change this line in your Home Component:
<Route exact path="/" render={(props) => <App {...props} />} />
import React from "react";
import App from "./App";
import { render } from "react-dom";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
Redirect,
} from "react-router-dom";
const Home = () => {
return (
<div>
<Router>
<Route exact path="/" render={(props) => <App {...props} />} />
<Route path="/:roomCode" component={App} />
</Router>
</div>
);
};
export default Home;
here is how to render it:
const appDiv = document.getElementById("app");
render(<Home />, appDiv);
now you can get the props
const App = (props) => {
console.log(props.match.params);
};
export default App;
You could try using the React hooks provided by the React Router framework. There are several different hooks used to interact with the router.
const App = () => {
const { roomCode } = useParams()
console.log(params);
};
More info here

React router history push always route to 404 page

js and facing hard time with react router dom.
I want to change the route when I click a button in my navigation drawer component.
This is my App.js component.
import { Router, Route, Switch } from "react-router-dom";
function App() {
const classes = useStyles();
return (
<Provider store={store}>
<div className={classes.root}>
<NavBar />
<Drawer />
<Router history={history}>
<Switch>
<Route path="/" exact component={Login}></Route>
<Route path="/country" exact component={Country}></Route>
<Route path="/user-create" exact component={User}></Route>
<Route path="/countries" exact component={ListView}></Route>
<Route component={NotFound}></Route>
</Switch>
</Router>
</div>
</Provider>
);
}
And here I pass history prop to the Router component.
History.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
Drawer.js
import history from '../../history'
const onRoute = (path) => {
history.push("/user-create");
// props.toggleDrawer();
}
In Drawer.js it is always route to the NotFoundComponet.
Why could this happen?
In your NavBar and Drawer components include the below withRouter or the alt useHistory hook to get access to the history prop.
import { withRouter } from 'react-router'
...
this.props.history.push('/user-create')
...
export default withRouter(...
I'd put <NavBar /> and <Drawer /> inside <Router>, and do
const { push } = useHistory() // from react-router-dom
inside them, to get a reference of the push API

Categories

Resources