Just started with React and wanted to define routes for my app. I understood the general concept of how react defines routes but my script that I basically wrote and don't understand a lot is slightly different from the examples found on youtube regarding routers. Can anyone help me?
App.js
import React, { Component, Fragment } from "react";
import ReactDOM from "react-dom";
import Header from "./layout/Header";
import Dashboard from "./users/Dashboard";
import Users from "./users/Users";
import { Provider } from 'react-redux';
import store from '../store';
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
class App extends Component {
render() {
return (
<Provider store={store}>
<Fragment>
<Header />
<div className="container">
<Dashboard />
</div>
</Fragment>
</Provider>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
You need to read the documentation: Documentation
But for start let me show you a simple usage:
First wrap your code with Router component:
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<Fragment>
<Header />
<div className="container">
<Dashboard />
</div>
</Fragment>
</Router>
</Provider>
);
}
}
Then you can specify which component has to be shown when some specific url is reached. Like below:
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<Fragment>
<div className="container">
<Route path="/dashboard" component={Dashboard} />
</div>
</Fragment>
</Router>
</Provider>
);
}
}
Using the above code will render the Header always. And it will render Dashboard component only when you are on the page with the /dashboard in the url.
Related
Hi i am new developer in ReactJS. I have a problem and want to learn how to make routing for dashboard. My root component is App component and it calls only dashboards of my pages. But I want to call different components inside of dashboard such as Login , Register etc. When I use "Link" in anywhere, How can I do this ? Could you help me at this issue?
index.tsx for BrowserRouter
import {BrowserRouter} from "react-router-dom";
const app =<App /> ;
const container = (
<>
<BrowserRouter>
{app}
</BrowserRouter>
</>
);
my router App.tsx component:
import { Route, Switch } from "react-router-dom";
import LoginDash from "../containers/login/LoginDash"
class App extends Component {
render() {
return (
<div className="App">
<Switch>
<Route path="/Login" exact component={LoginDash}></Route>
<Route path="/" exact component={LoginDash}></Route>
</Switch>
</div>
);
}
}
export default App;
My dashboard LoginDash.tsx:
import {BrowserRouter as Router, Route,Switch} from "react-router-dom"
import LoginPart from "../../components/login/left/LoginPart";
import RegisterPart from "../../components/login/left/RegisterPart";
import AnitamionPart from '../../components/login/right/AnimationPart';
export const Login = () => {
return (
<div className="login-container">
<div className="row login-row" >
<div className="login-left-part" >
<Router>
<Switch>
<Route exact path = "/Login" component={LoginPart}></Route>
<Route exact path = "/Register" component={RegisterPart}></Route>
</Switch>
</Router>
</div>
<div className=" login-right-part" >
<AnitamionPart></AnitamionPart>
</div>
</div>
</div>
)
}
export default Login;
First of all, you only need to use one instance of BrowserRouter in your App, Since you already wrap App component with BrowserRouter that would be enough
Secondly, if you specify exact attribute on Routes, no nested Routes will ever match. Make sure you don't use Route with exact prop if the component has any nested Route defined
Lastly, you only need to render LoginDash on / route, /Login handling can be done separately as a nested Route
Update your individual components like below
import {BrowserRouter} from "react-router-dom";
// Do not render app as a constant separetely,
const container = (
<>
<BrowserRouter>
<App />
</BrowserRouter>
</>
);
import { Route, Switch } from "react-router-dom";
import LoginDash from "../containers/login/LoginDash"
class App extends Component {
render() {
return (
<div className="App">
<Route path="/" component={LoginDash}></Route>
</div>
);
}
}
export default App;
export const Login = () => {
return (
<div className="login-container">
<div className="row login-row" >
<div className="login-left-part" >
<Switch>
<Route exact path = "/Login" component={LoginPart}></Route>
<Route exact path = "/Register" component={RegisterPart}></Route>
</Switch>
</div>
<div className=" login-right-part" >
<AnitamionPart></AnitamionPart>
</div>
</div>
</div>
)
}
export default Login;
Working demo
I have been trying to redirect the page using <Link> and what i have is that the URL changes but the page does not redirect. Only after i refresh the page, it show.
I have searched and found some links:
1. One on the correct syntax
2. i have implemented the link in small HTML
Now here is the part of my Code
App.Js
import React from 'react';
import { Switch , Route , BrowserRouter } from 'react-router-dom';
import HomePage from './section/home';
import Oneup from './section/oneup';
function App() {
return (
<div className="main homepage">
<BrowserRouter>
<div>
<Switch>
<Route path="/" component={HomePage} exact={true} />
<Route path="/oneup" component={Oneup} exact={true} />
</Switch>
</div>
</BrowserRouter>
</div>
);
}
main_content.js
Here i have included <Link>
import React from 'react';
import { BrowserRouter, Link } from "react-router-dom";
class Main_content extends Component {
render() {
return (
<div class="ib-center">
<BrowserRouter>
<Link to="/oneup" class="btn">VIEW CASE</Link>
</BrowserRouter>
</div>
)
}
}
Now i can't figure out where i am going wrong.
the link generated is fine and working when refreshed manually.
Use one BrowerRouter to wrap, you have used BrowerRouter in App.js and main_content.js too
class Main_content extends Component {
render() {
return (
<div class="ib-center">
<div>
<Link to="/oneup" class="btn">VIEW CASE</Link>
</div>
</div>
)
}
It seems my application will not render the component passed to <Route /> unless I refresh the page. What could I be doing wrong?
components/App/index.jsx
// dependencies
import React from 'react';
import PropTypes from 'prop-types';
import { Provider } from 'react-redux';
import { BrowserRouter as Router } from 'react-router-dom'
// components
import Header from '../Header';
// containers
import SidebarContainer from '../../containers/SidebarContainer';
import MainContainer from '../../containers/MainContainer';
const App = ({store}) => (
<Provider store={store}>
<Router>
<div className="wrapper">
<Header />
<div className="container-fluid container-fluid--fullscreen">
<div className="row row--fullscreen">
<SidebarContainer />
<MainContainer />
</div>
</div>
</div>
</Router>
</Provider>
);
App.propTypes = {
store: PropTypes.object.isRequired,
};
export default App;
containers/MainContainer.jsx
// dependencies
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Route } from 'react-router-dom'
// components
import Dashboard from '../components/Dashboard';
import List from '../components/List';
// containers
import LoginContainer from './LoginContainer.jsx'
class Main extends Component {
render() {
console.log(this.props)
return(
<div className="wrapper">
<Route exact path="/" component={Dashboard} />
<Route path="/login" component={LoginContainer} />
<Route path="/users" component={List} />
</div>
);
}
}
const mapStateToProps = (state) => {
return {
token: state.authentication.token,
};
};
const MainContainer = connect(mapStateToProps, null)(Main);
export default MainContainer;
So it seems when I click on a <Link to="/users" /> component my path changes to http://localhost:3000/users but the component does not change from Dashboard to List
I'm also noticing that when I console.log this.props from MainContainer I do not see anything related to router such as this.props.location.pathname --perhaps I'm not structuring my application correctly?
After poking around the react-router issues page on github I found this thread: https://github.com/ReactTraining/react-router/issues/4671
It appears as though the redux connect method blocks context which is required by react-router package.
That being said, the fix for this is to wrap all redux connected components that have router components inside with withRouter() like so:
containers/MainContainer.jsx
// dependencies
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Route, withRouter } from 'react-router-dom' // IMPORT withRouter
// components
import Dashboard from '../components/Dashboard';
import List from '../components/List';
// containers
import LoginContainer from './LoginContainer.jsx'
class Main extends Component {
render() {
console.log(this.props)
console.log(this.context)
return(
<div className="wrapper">
<Route exact path="/" component={Dashboard} />
<Route path="/login" component={LoginContainer} />
<Route path="/users" component={List} />
</div>
);
}
}
const mapStateToProps = (state) => {
return {
token: state.authentication.token,
};
};
// WRAP CONNECT METHOD
const MainContainer = withRouter(connect(mapStateToProps, null)(Main));
export default MainContainer;
I think you have to do little more tweak in your code to make it work. Assuming you use react-router v4, the following should solve your problem.
import { BrowserRouter, Route, Switch } from 'react-router-dom';
<Provider store={store}>
<BrowserRouter>
<div>
<Switch>
<SidebarContainer />
<MainContainer />
</Switch>
</div>
</BrowserRouter>
</Provider>
I have a working copy of the same code only differs come from typescript.
And this the code below somehow and exception message..
import * as React from 'react';
import Home from '../Home/Home';
import User from '../User/User';
import {
BrowserRouter as Router,Route,Link,Switch} from 'react-router-dom'
class Layout extends React.Component<{},{}> {
render() {
return (
<Router>
<div className="App">
<Switch>
<Route exact path="/" component={Home} />
<Route path="/user/:id" userid="25" component={User}/>
<Route component={Notfound}/>
</Switch>
</div>
</Router>
);
}
}
and one of my component, home.tsx:
import * as React from 'react';
class Home extends React.Component<{},{}> {
render() {
return (
<div className="App">
Welcome Home Page!
</div>
);
}
}
Whats wrong here ?
Here is how I fixed the problem. As a commenter explained, there is some confusion for the compiler on how to explicitly handle passing in props.
App.tsx:
import * as React from 'react';
import './App.css';
interface State { }
// tslint:disable-next-line
class App extends React.Component<any, State> {
render() {
return (
<div className="App">
HIIIII
</div>
);
}
}
export default App;
index.tsx:
...
ReactDOM.render(
<Router>
<div>
<Route path="/" component={App} />
</div>
</Router>,
document.getElementById('root') as HTMLElement
);
I have not found a better solution yet. But this will indeed work.
I have a situation where I require to render two different components at two DIFFERENT ids. Something like this:
ReactDOM.render(
<Component1/>,
document.getElementById('Coponent-id-1'));
and:
var deal_recommendations_id = document.getElementById('deal_recommendations_app');
ReactDOM.render(
<Component2/>,
document.getElementById('Coponent-id-2'));
P.S This is different scenario than wrapping two component with a
div and then rendering it on a single id
I'm actually trying to do this:
ReactDOM.render((
<Provider store={store}>
<Router history={hashHistory}>
<Route path="/" component={WizardApp}> </Route>
<Route path="/overview" component={DealRecommendation}></Route>
<Route path="/overview/:deal" component={DealRecommendation}></Route>
<Route path="/users/invite" component={ReferralApp}></Route>
<Route path="/adm/custodian" component={CustodianApp}></Route>
</Router>
</Provider>
), document.getElementById('appRoot')
);
var deal_recommendations_id = document.getElementById('deal_recommendations_app');
ReactDOM.render(
<DealRecommendation/>,
deal_recommendations_id);
P.P.S In normal cases it works fine as shown in the answers.
In my case, at deal_recommendations_id three Links(react Links) are loaded. when I click on any of these, I get an error message:
Link.js:95 Uncaught TypeError: Cannot read property 'pushState' of undefined
Here is the complete snippet:
import React, { Component } from 'react';
import ReactDOM from "react-dom";
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
// import App from './components/App';
import WizardApp from './components/WizardApp';
import DealRecommendation from './components/dealRecommendation';
import ReferralApp from './components/referral/ReferralApp';
import CustodianApp from './components/admin/custodian/CustodianApp';
import { Router, Route, IndexRoute, Link, browserHistory, hashHistory } from 'react-router'
const store = createStore(rootReducer,compose(
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : f => f
));
ReactDOM.render((
<Provider store={store}>
<Router history={hashHistory}>
<Route path="/" component={WizardApp}> </Route>
<Route path="/overview" component={DealRecommendation}></Route>
<Route path="/overview/:deal" component={DealRecommendation}></Route>
<Route path="/users/invite" component={ReferralApp}></Route>
<Route path="/adm/custodian" component={CustodianApp}></Route>
</Router>
</Provider>
), document.getElementById('appRoot')
);
var deal_recommendations_id = document.getElementById('deal_recommendations_app');
ReactDOM.render(
<DealRecommendation/>,
deal_recommendations_id);
See the snapshot. The upper div works fine (in this case, this.props.params are getting populated too). However, the lower div which I think gets initialized even before the <Routers> are defined is causing the problem I think. (in this case, this.props.params is coming as undefined)
-------------------DealRecommendation.js------------------------------------
import React from "react";
import ReactDOM from "react-dom";
import { Router, Route, IndexRoute, Link, browserHistory, hashHistory } from 'react-router';
import { createHistory } from 'history';
import RouterTabs from "./dealsOfInterest/routerTabs"
import '../style/deal_recommendation.css';
export default class DealRecommendation extends React.Component{
constructor(){
super();
}
render(){
if(this.props.params!=undefined){
if(this.props.params.deal==="rec_act"){
return(
<div className="deal_data_wrapper">
<h3>Deals of Interest</h3>
<RouterTabs/>
<h2>this is activity</h2>
</div>
)
}
else if(this.props.params.deal==="deal_news"){
return(
<div className="deal_data_wrapper">
<h3>Deals of Interest</h3>
<RouterTabs/>
<h2>This is Deal_news</h2>
</div>
)
}
else{
return(
<div className="deal_data_wrapper">
<h3>Deals of Interest</h3>
<RouterTabs/>
<h2>This works too</h2>
</div>
)
}
}
else{
return(
<div className="deal_data_wrapper">
<h3>Deals of Interest</h3>
<RouterTabs/>
<h2>This doesn't work</h2>
</div>
)
}
}
}
It is perfectly fine to use two ReactDOM.render() in a single script.
See example below
var Hello = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
var HelloAgain = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
ReactDOM.render(
<HelloAgain name="World again" />,
document.getElementById('another-container')
);
JSFIDDLE
Refer to the following articles
React Forum, SO POST
In your case
var deal_recommendations_id = document.getElementById('deal_recommendations_app');
ReactDOM.render(
<DealRecommendation/>,
document.getElementById('deal_recommendations_id'));
deal_recommendation_id is already a DOM element and not an id you need not use document.getElementById again. Use it like below
var deal_recommendations_id = document.getElementById('deal_recommendations_app');
ReactDOM.render(
<DealRecommendation/>,
deal_recommendations_id);
EDIT:
As far as I can see you need to remove the redundant route for dealrecommendation
ReactDOM.render((
<Provider store={store}>
<Router history={hashHistory}>
<Route path="/" component={WizardApp}> </Route>
<Route path="/overview/:deal" component={DealRecommendation}></Route>
<Route path="/users/invite" component={ReferralApp}></Route>
<Route path="/adm/custodian" component={CustodianApp}></Route>
</Router>
</Provider>
), document.getElementById('appRoot')
);
var deal_recommendations_id = document.getElementById('deal_recommendations_app');
ReactDOM.render(
<DealRecommendation/>,
deal_recommendations_id);
Is this what you are after? http://codepen.io/PiotrBerebecki/pen/kkyYJv
The script tag to your js file should be put at the bottom of the body tag (below the targeted ids).
HTML:
<head>
<title>React JS</title>
</head>
<body>
<div id="app1"></div>
<div id="app2"></div>
<script src="/index.js"></script>
</body>
</html>
JS:
class Component1 extends React.Component {
render() {
return (
<div>Hello React from Component 1</div>
);
}
}
class Component2 extends React.Component {
render() {
return (
<div>Hello React from Component 2</div>
);
}
}
ReactDOM.render(
<Component1 />,
document.getElementById('app1')
);
ReactDOM.render(
<Component2 />,
document.getElementById('app2')
);