How to navigate outside of components using react-router-dom and BrowserRouter - javascript

I am using BrowserRouter and i want to navigate outside of component. I can navigate using Router but can i do using BrowserRouter
import { createBrowserHistory } from 'history';
export const history = createBrowserHistory();
<Router history = {history}>
<Switch>
<Route
path="/"
component={Home}
exact={true} />
<Route
path="/somePath"
component={SomeDisplay}
exact={true} />
</Router>
And I can use it outside component as
import { history } from 'path/to/RouterConfigurations';
export const func1 = () => {
history.push({
pathname: "/somePath"
});
}

Related

React Router: Component not getting displayed

I have just started with React and not able to get the router working. Below is the code for router. If I use the individual components without the router, they are displayed on the screen. But with router I don't get any text on the screen across any of the paths.
Please let me know if I am missing something. Below is the code:
import { Route } from 'react-router-dom';
import AllMeetupsPage from './pages/AllMeetups';
import NewMeetupPage from './pages/NewMeetup';
function App() {
return (
<div>
<Route path='/' exact>
<AllMeetupsPage />
</Route>
<Route path='/new-meetup'>
<NewMeetupPage />
</Route>
</div>);
}
export default App;
A route needs to be a descendent of router component. I'm not sure which version of react-router you're using, but this will be a BrowserRouter and Routes component for react-router v6 and on v4/v5 it'll be a BrowserRouter
Here's some examples:
v6:
import {
BrowserRouter,
Routes,
Route
} from "react-router-dom";
import AllMeetupsPage from './pages/AllMeetups';
import NewMeetupPage from './pages/NewMeetup';
function App() {
return (
<div>
<BrowserRouter>
<Routes>
<Route path="/" exact element={<AllMeetupsPage />}/>
<Route path="/new-meetup" element={<NewMeetupPage />}/>
</Routes>
</BrowserRouter>
</div>);
}
export default App;
You missed using Switch component
import { Route , Switch } from 'react-router-dom';
function App() {
return (
<div>
<Switch>
<Route path='/' exact>
<AllMeetupsPage />
</Route>
<Route path='/new-meetup'>
<NewMeetupPage />
</Route>
</Switch>
</div>);
}
export default App;

Unmounted component with react-router

I have a problem with my react router when I want to pass from a router to another.
I have a Connexion files :
import React from "react";
import {
Switch,
BrowserRouter as Router,
Route,
Redirect,
} from "react-router-dom";
import SignIn from "./Containers/Login/Login";
import Player from "./Player";
const Routes = () => {
return (
<Router>
<Switch>
<Route exact path="/" component={SignIn} />
<Route path="/app/player/" component={Player} />
<Route path="/*">
<Redirect to="/" />
</Route>
</Switch>
</Router>
);
};
export default Routes;
When I connect from "SignIn", I want to go in the next route "Player" :
import React from "react";
import {
Switch,
BrowserRouter as Router,
Route,
useRouteMatch,
} from "react-router-dom";
import Navigation from "./Navigation/PlayerNavigation";
import FillCollect from "./Containers/Collect/Collect";
import Dashboard from "./Containers/Dashboard/Dashboard";
const Player = () => {
const { path } = useRouteMatch();
console.log(path);
return (
<Router>
<Navigation />
<Switch>
<Route path={`${path}/collect/:id`} component={FillCollect} />
</Switch>
</Router>
);
};
export default Player;
(My Navigation component is my sidebar and topbar)
But when I'm connect my Navigation is displayed but not my Fill Collect ! And i have this warning :
Warning: Can't perform a React state update on a unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect clean function.
In SignIn (created by Context.Consumer)
I tried to display a minimalist component with just div but it's the same
There are a couple of problems in this
Firstly you are using a nested Router component too, which then restricts the inner Routes from listening to the router Router component
Secondly, your matchPath in parent is "/app/player/" which if you combine with the nested Route in child like ${path}/collect/:id. It becomes "/app/player//collect/:id" which is not what you indent
The working solution will be as follows
const Routes = () => {
return (
<Router>
<Switch>
<Route exact path="/" component={SignIn} />
<Route path="/app/player" component={Player} />
<Route path="/*">
<Redirect to="/" />
</Route>
</Switch>
</Router>
);
};
export default Routes;
const Player = () => {
const { path } = useRouteMatch();
console.log(path);
return (
<React.Fragment>
<Navigation />
<Switch>
<Route path={`${path}/collect/:id`} component={FillCollect} />
</Switch>
</React.Fragment>
);
};
export default Player;

How to reroute my react app after an asynchronous api request

I am working on rerouting my application. I have a form, I want the user to be redirected after the form is submitted successfully. I placed the logic after the api is successful. My url changes but the component that is meant to be loaded on that url does not load.
import { browserHistory } from '../router/router';
...
export const storeRecord=(data)=>{
return function(dispatch, getState){
//console.log('state',getState());
const {authToken, userId} = getState().authReducer;
token= authToken;
data.userId = userId;
const url = 'investment/store';
apiCall(url, data, dispatch,'post').then((data)=>{
try{
if(data.status=== 200){
//let data = apiResponse.data
console.log('success',data);
browserHistory.push('/');
//dispatch(push('/'));
}
}
catch(error){
console.log('returnedError',error);
}
}, (error)=>{console.log(error)});
}
}
Here is my route as well:
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { createBrowserHistory } from 'history';
...
export const browserHistory = createBrowserHistory();
const AppRouter=()=>{
return(<Router>
<LoaderModal />
<Switch>
<Route path="/" exact component={LandingPage} />
<PublicRouter path="/register" exact component={SignupPage} />
<PublicRouter path="/login" exact component={LoginPage} />
<PrivateRoute path="/investment/new" exact component={InvestmentForm} />
<Route component={NotFoundPage} />
</Switch>
</Router>)
}
export default AppRouter;
I am using react-router-dom for rerouting and history for the browser re-routing.
You can use following code in place of dispatch(push('/')) which you used in storeRecord component.
window.location.assign('/');
You need to use the same history object that your Router modules uses to dynamically Route.
The easiest solution is for you to not use browserRouter but to use a Router with custom history
import React from 'react';
import { Router, Route, Switch } from 'react-router-dom';
import { createBrowserHistory } from 'history';
...
export const browserHistory = createBrowserHistory();
const AppRouter=()=>{
return(<Router history={browserHistory}>
<LoaderModal />
<Switch>
<Route path="/" exact component={LandingPage} />
<PublicRouter path="/register" exact component={SignupPage} />
<PublicRouter path="/login" exact component={LoginPage} />
<PrivateRoute path="/investment/new" exact component={InvestmentForm} />
<Route component={NotFoundPage} />
</Switch>
</Router>)
}
export default AppRouter;
and then your action will look like
import { browserHistory } from '../router/router';
...
export const storeRecord=(data)=>{
return function(dispatch, getState){
const {authToken, userId} = getState().authReducer;
token= authToken;
data.userId = userId;
const url = 'investment/store';
apiCall(url, data, dispatch,'post').then((data)=>{
try{
if(data.status=== 200){
browserHistory.push('/');
}
}
catch(error){
console.log('returnedError',error);
}
}, (error)=>{console.log(error)});
}
}

Why cant I separate <Switch> to a different module?

Goal
I'm trying to extract the <Switch> with its <Route>'s out to a different module.
Problem
The url is being changed to the new path, but the content doesn't (only when I refresh it changes).
I'm trying to understand what am I missing.
EDITED:
live example: https://stackblitz.com/edit/separated-switch-module
working example:
<BrowserRouter>
<div>
<Link to="/"> Home </Link>
<Link to="contacts"> Contacts </Link>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/contacts" component={Contacts} />
</Switch>
</div>
</BrowserRouter>
failing exmaple:
<BrowserRouter>
<div>
<Link to="/"> Home </Link>
<Link to="contacts"> Contacts </Link>
<SwitchedRoutes/>
</div>
</BrowserRouter>
EDITED:
SwitchedRoutes:
import React from "react";
import { observer, inject } from "mobx-react";
import { Switch, Route } from "react-router-dom";
#inject('pageStore')
#observer
export default class extends React.Component {
render(){
const {
home,
contacts
} = this.props.pageStore.pages;
return (
<Switch>
<Route exact path={home.path} render={()=> <Home />} />
<Route path={contacts.path} render={()=> <Contacts/>} />
</Switch>
)
}
}
Since react-router v4 changed an API a bit you need to give to the all underlying components such as Switch, Link and etc a router context. (Something like subscriber to the routing stuff), as soon as you disconnects the module to the separate file it loses the context.
just add this to the SwitchedRoutes.js
import React from 'react';
import { withRouter } from 'react-router'
import {Switch, Route} from 'react-router-dom';
import {inject, observer} from 'mobx-react';
const Home = () => <h1>Home</h1>;
const Contacts = () => <h1>Contents</h1>;
const switchedRouter = inject('store')(observer(props => {
const {home, contacts} = props.store.routes;
return(
<Switch>
<Route exact path={home.path} component={Home}/>
<Route path={contacts.path} component={Contacts}/>
</Switch>
);
}));
export default withRouter(switchedRouter)
we simply wrapped the component with withRouter HoC which provides us a correct react-router context.
https://separated-switch-module-j92psu.stackblitz.io

warning.js:36 Warning: Failed prop type: The prop `history` is marked as required in `Router`, but its value is `undefined`

Getting the error in the title based on the following code:
import React from 'react'
// import { browserHistory, hashHistory, Router } from 'react-router'
// import createMemoryHistory from 'history/lib/createMemoryHistory'
import { browserHistory, hashHistory, Router, Route, Switch } from 'react-router-dom'
import Portfolio from './portfolio/Portfolio'
import Home from './home/Home'
import NoMatch from './NoMatch'
// const history = createMemoryHistory(location);
// console.log('history', history);
const Routes = () => {
return (
<Router history={browserHistory}>
<Route exact={ true } path="/" component={ Home }/>
<Route exact={ true } path="/portfolio" component={ Portfolio }/>
<Route component={ NoMatch } />
</Router>
);
}
export default Routes
Replace Router with BrowserRouter and use Switch as from react-router-dom version4.0, Router can not have more than one child.
import { browserHistory, hashHistory, BrowserRouter, Route, Switch } from 'react-router-dom';
and replace routes with below code:
const Routes = () => {
return (
<BrowserRouter history={browserHistory}>
<Switch>
<Route exact={ true } path="/" component={ Home }/>
<Route exact={ true } path="/portfolio"
component={ Portfolio }/>
<Route component={ NoMatch } />
</Switch>
</BrowserRouter>
);
}

Categories