not being able to pass url parameters in react.js - javascript

I am working on a React.js web app , for some reasons I am not able to pass url parameters.
An example is being shown below:
Routes:
import React from "react";
import {BrowserRouter, Route, Switch, Redirect} from 'react-router-dom';
import Helloworld from './components/helloworld/helloworld.component';
import SecondView from './components/secondview/secondview.component';
import ThirdView from "./components/thirdview/thirdview.component";
const AppRoutes = () => (
<BrowserRouter>
<Switch>
<Route exact path='/' component={Helloworld}/>
<Route path='/secondview' component={SecondView}/>
<Route path='/thirdview' component={ThirdView}/>
<Route path='/thirdview/:number' component={ThirdView}/>
<Redirect from='*' to='/' />
</Switch>
</BrowserRouter>
);
export default AppRoutes;
Secondview Component
import React from 'react';
import {Link, withRouter} from 'react-router-dom';
class SecondView extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log("I am being called SecondView component...");
}
render() {
return (
<div className={"boxDiv"}>
<p>Second View</p>
<Link to={{pathname: '/thirdview/7'}}> GO to third view with parameter value. </Link>
</div>
);
}
}
export default withRouter(SecondView);
Thirdview comopnent:
import React from 'react';
import { Route, Link,withRouter } from 'react-router-dom';
import FourthView from "../fourthview/fourthview.component";
class ThirdView extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
}
render() {
console.log(this.props.match.params);
return (
<div className={"boxDiv"}>
<p>Third View</p>
{ console.log(this.props)}
<h1>parameter passed: (#{this.props.params.number})</h1>
</div>
);
}
}
export default withRouter(ThirdView);
What I want, is to be able to get /:number value on my thirdview component! Anyone knows how to achieve such thing in React.js? Are there other ways doing this?
What I get is empty object!

I think it should be:
{this.props.match.params.number}
instead of
{this.props.params.number}
and you don't need withRouter on ThirdView and SecondView as are passed to Route already.
EDIT:
Since you want to render the same component for /thirdview and /thirdview/7 use optional param matcher
<Switch>
<Route exact path='/' component={Helloworld}/>
<Route path='/secondview' component={SecondView}/>
<Route path='/thirdview/:number?' component={ThirdView}/>
<Redirect from='*' to='/' />
</Switch>

Related

React Router not render

I tried using react router but it doesn't work. I already know that React Router Dom v6 has changed from Switch to Routes but when I run the program it just shows a blank screen. Does anyone know how to fix this? Here is my code:
App.js
'''
import React, {Component} from "react";
import { BrowserRouter as Router } from "react-router-dom";
import { render } from "react-dom";
import HomePage from "./HomePage";
export default class App extends Component{
render() {
return (
<Router>
<div>
<HomePage />
</div>
</Router>
);
}
}
const appDiv = document.getElementById("app");
render(<App />,appDiv);
'''
HomePage.js
'''
import React,{Component} from 'react';
import RoomJoinPage from "./RoomJoinPage";
import CreateRoomPage from "./CreateRoomPage";
import { BrowserRouter as Router ,
Routes ,
Route ,
} from "react-router-dom"
export default class HomePage extends Component{
render () {
return (
<Router>
<Routes>
<Route path='/'>
<p>This is Home Page</p>
</Route>
<Route path='/join' element={<RoomJoinPage />} />
<Route path='/create' element={<CreateRoomPage />} />
</Routes>
</Router>
);
}
}
'''
The error is that "You cannot render a Router inside another Router " occurs when we have 2 Router components in the same React application.
So if u see u are calling in App.js and when u call Homepage from app.js it renders again. Thats why everything becomes blank.
and avoid using p tag inside render function in homepage.js
Try doing this:
**App.js**
import React, {Component} from "react";
import { BrowserRouter as Router } from "react-router-dom";
import { render } from "react-dom";
import HomePage from "./HomePage";
export default class App extends Component{
render() {
return (
<div>
<HomePage />
</div>
);
}
}
const appDiv = document.getElementById("app");
render(<App />,appDiv);
**Homepage.js**
import React,{Component} from 'react';
import RoomJoinPage from "./RoomJoinPage";
import CreateRoomPage from "./CreateRoomPage";
import { BrowserRouter as Router ,
Routes ,
Route ,
} from "react-router-dom"
export default class HomePage extends Component{
render () {
return (
<Router>
<Routes>
<Route path='/'>
</Route>
<Route path='/join' element={<RoomJoinPage />} />
<Route path='/create' element={<CreateRoomPage />} />
</Routes>
</Router>
);
}
}

React - React Router - A <Router> may have only one child element

I'm a newbie at React, please correct me if I'm wrong...I've used the Switch tag to enclose multiple Routes in my MainComponent.js file. However, I still got an error that says "A may have only one child element". I'm trying to navigate from one page to another.
For example, when I click on Menu in the landing page, I would like to get routed to Menu.
Please advise what went wrong. Thanks in advance.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'font-awesome/css/font-awesome.css';
import 'bootstrap-social/bootstrap-social.css';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
App.js
import React, { Component } from 'react';
import Main from './components/MainComponent';
import './App.css';
import { BrowserRouter } from 'react-router-dom';
class App extends Component {
// pass dishes to children (MenuComponent.js) as props
/*
constructor(props) {
super(props);
this.state = {
dishes: DISHES
};
}*/
render() {
return (
<BrowserRouter> {/* Make use of React Router */}
<div className="App">
<Main />
</div>
</BrowserRouter>
);
}
}
export default App;
MainComponent.js
// Container Component
import React, { Component } from 'react';
import Menu from './MenuComponent';
import DishDetail from './DishdetailComponent';
import Header from './HeaderComponent';
import Footer from './FooterComponent';
import Home from './HomeComponent';
import { DISHES } from '../shared/dishes'; // .. means to go up one level to src
import { Switch, Route, Redirect } from 'react-router-dom';
class Main extends Component {
// pass dishes to children (MenuComponent.js) as props
constructor(props) {
super(props);
this.state = {
dishes: DISHES,
// selectedDish: null
};
}
/*
onDishSelect(dishId) {
this.setState({selectedDish: dishId});
}
*/
render() {
const HomePage = () => {
return (
<Home />
);
}
return (
<div>
<Header />
<Switch>
<Route path="/home" component={HomePage} />
<Route exact path="/menu" component={() => <Menu dishes={this.state.dishes} />} /> {/* path should exactly match /menu and nothing else after /menu */}
{/* component={() => <Menu dishes={this.state.dishes} />} ----> this will allow to pass props to Menu component */}
<Redirect to="/home" /> {/* if the path doesn't match any above, redirect to /home */}
</Switch>
<Footer />
</div>
);
}
}
export default Main;
Just remove the <div className="App"> from your App.js file.
And use the below code as I have written below. It will 100% work for you.
import { BrowserRouter } from 'react-router-dom';
class App extends Component
{
render() {
return (
<BrowserRouter>
<Main/>
</BrowserRouter>
);
}
}
export default App;

Route Component renders multiple times when route is split into multiple files

The issue is that whenever I try to migrate my routes into another file and import them into parent file(routes.js) then whenever I tried to navigate to those migrated route the whole layout is re-rendered and if I keep migrated routes in the parent route component then the layout is rendered once as expected.
The route component where all the routes are written as below
routes.js
import React, { Component } from 'react';
import {Route, Switch} from 'react-router-dom';
import PrivateRoute from './PrivateRoute';
import MainLayout from '../pages/layouts/MainLayout';
import Login from '../components/Login/Login';
import UserList from "../components/User/UserList";
import UserCreate from '../components/User/UserCreate';
import UserEdit from '../components/User/UserEdit';
import UserSetting from '../components/User/UserSetting';
class Main extends Component {
render() {
return (
<Switch>
<Route exact path='/' component={Login}/>
<PrivateRoute exact path='/user' component={UserList} layout={MainLayout}/>
<PrivateRoute exact path='/user/create' component={UserCreate} layout={MainLayout}/>
<PrivateRoute exact path='/user/edit/:id' component={UserEdit} layout={MainLayout}/>
<PrivateRoute exact path='/user/setting/:id' component={UserSetting} layout={MainLayout}/>
</Switch>
)
}
}
export default Main;
UserRoutes.js
import UserList from "../components/User/UserList";
import UserCreate from '../components/User/UserCreate';
import UserEdit from '../components/User/UserEdit';
import UserSetting from '../components/User/UserSetting';
const UserRoutes = [
{
path : '/user',
component : UserList,
},
{
path : '/user/create',
component : UserCreate,
},
{
path : '/user/edit/:id',
component : UserEdit,
},
{
path : '/user/setting/:id',
component : UserSetting,
},
];
export default UserRoutes;
Now, when I try to import this route in place of the written routes in routes.js component, the above mentioned issue arises.
routes.js
import React, { Component } from 'react';
import {Route, Switch} from 'react-router-dom';
import PrivateRoute from './PrivateRoute';
import MainLayout from '../pages/layouts/MainLayout';
import Login from '../components/Login/Login';
import UserRoutes from './UserRoutes';
class Main extends Component {
render() {
return (
<Switch>
<Route exact path='/' component={Login}/>
{
UserRoutes.map(({ path, component }, key) =>
<PrivateRoute exact layout={MainLayout} path={path} component={component} key={key} />
)
}
</Switch>
)
}
}
export default Main;
PrivateRoute.js
import React from 'react';
import {Redirect, Route, withRouter} from 'react-router-dom';
let state_of_state = localStorage["appState"];
let Auth = {};
if (!state_of_state){
localStorage["appState"] = JSON.stringify({user : {}});
} else {
Auth = JSON.parse(state_of_state);
}
const PrivateRoute = ({ layout: Layout, component: Component, ...rest }) => (
<Route {...rest} render={props => {
const newComponent = Layout ?
<Layout><Component {...rest} {...props} /></Layout>
:
<Component {...props} />;
return (!_.isEmpty(Auth.user)) ? (
newComponent
) : (
<Redirect to={{pathname: '/', state: { from: props.location }}} />
)
}}/>
);
export default PrivateRoute;
I need some guidance where I am going wrong with this.

React not displaying correct route

I am putting together a small application to get used to React, now I have installed React-Router-Dom and when I click a link the URL correctly changes. The issue is that the correct Component does not display.
index.js
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root')
);
registerServiceWorker();
App.js
import React, { Component } from 'react';
import Sidebar from './Components/Sidebar';
import SidebarItem from './Components/SidebarItem';
import Home from './Components/Home';
import './App.scss';
import { Link, Route, Switch } from 'react-router-dom';
class App extends Component {
constructor() {
super();
this.state = {};
}
render() {
return (
<div className="App">
<Link to='/home'>Home</Link>
<Switch>
<Route path='/home' Component={Home} />
</Switch>
</div>
);
}
}
export default App;
Can anyone tell me the reason why HomeComponent does not appear?
The prop of the Route that takes a component is spelled component with a small c, not Component.
Example
function Home() {
return <div> Home </div>;
}
class App extends Component {
render() {
return (
<Router>
<div>
<Link to="/home">Home</Link>
<Switch>
<Route path="/home" component={Home} />
</Switch>
</div>
</Router>
);
}
}

React Route Redirect

I read all possible thread about programmatically redirection in React but I couldn't make it working.
My code looks like this (I removed as much I could to make it shorter):
import React from 'react';
import {render} from 'react-dom';
import {BrowserRouter as Router, Route, Switch} from "react-router-dom";
import {Login} from "./login/Login";
class App extends React.Component {
login(loginResponse) {
...
# Here I want to redirect but it does not work
this.props.history.push('/some-path/');
}
render() {
return (
<Router>
<div>
<div id="content">
<Messages />
<Switch>
<Route path="/" exact={true} component={Welcome} />
...
<Route path="/portal/login" render={() => <Login sendMessage={this.sendMessage} />} />
</Switch>
</div>
</div>
</Router>
);
}
}
render(<App/>, document.getElementById("app"));
I'd like to redirect when the login method is called to a different path.
With this.props.history.push('/some-path/'); I get Cannot read property 'push' of undefined.
In most of the places I read about withRouter but I could not make it work.
What am I missing to get the history?
Or what's the easiest to make the redirect work?
Thanks in advance
I think the main problem here is that I was trying to implement the redirect on the top level component.
I ended up moving a bit of login around and do the redirect from the Login component that is rendered thanks to the Route component therefore can access the history.
This is the code I used:
main.js
import React from 'react';
import {render} from 'react-dom';
import {BrowserRouter as Router, Route, Switch} from "react-router-dom";
import {Login} from "./login/Login";
class App extends React.Component {
render() {
return (
<Router>
<div>
<div id="content">
<Messages />
<Switch>
<Route path="/" exact={true} component={Welcome} />
...
<Route path="/portal/login" render={(router) => <Login router={router} sendMessage={this.sendMessage} />} />
</Switch>
</div>
</div>
</Router>
);
}
}
render(<App/>, document.getElementById("app"));
Login.js
import React from 'react';
export class Login extends React.Component {
constructor(props) {
super(props);
this.onLoginResponse = this.onLoginResponse.bind(this);
}
onLoginResponse(loginResponse) {
...
this.props.router.history.push('/portal/');
}
render() {
return (
<div id="login-form">
Login page ...
</div>
);
}
}
The nice thing of this is that now the code for handling a login response is in the Login page.
But as I wanted to store the user who logged in into the main app status I needed to do some extra work.

Categories

Resources