I am having a problem understanding how routes and pages should be structured using react-router, I learn the principles of react and am working off of a post placed on 24ways currently. The issue I am facing is the ability to import components.
For example I have my router setup as such:
// Router
export const routes = {
path: '',
component: appComponent,
childRoutes: [
{
path: '/',
components: {nav: navbarComponent, content: indexComponent}
},
{
path: '/join',
component: {nav: navbarComponent, content: joinComponent}
}
]
};
// appComponent
import React from 'react';
export default class appComponent extends React.Component {
render() {
const { nav, content } = this.props;
return (
<div>
<div className="nav">
{nav}
</div>
<div className="content">
{content}
</div>
</div>
);
}
}
Is there a way that I don't have to do this an instead am able to directly import into each of my components, for example this instead:
// Router
export const routes = {
path: '',
component: appComponent,
childRoutes: [
{
path: '/',
components: indexComponent
},
{
path: '/join',
component: joinComponent
}
]
};
// appComponent
import React from 'react';
import Navbar from 'Navbar';
export default class appComponent extends React.Component {
render() {
return (
<div>
<Navbar />
{this.props.children}
</div>
);
}
}
Have been searching all over and can't find a solution to this problem, would like to use react-router and react but it currently does not seem feasible if this is not possible. From my understanding of react the ability to build and reuse components within one another was possible.
Here is the navbar component:
import React from 'react';
import Navbar from 'react-bootstrap/lib/Navbar';
import Nav from 'react-bootstrap/lib/Nav';
import NavItem from 'react-bootstrap/lib/NavItem';
export default class navbarComponent extends React.Component {
render () {
return (
<Navbar inverse>
<Navbar.Header>
<Navbar.Brand>
React-Bootstrap
</Navbar.Brand>
<Navbar.Toggle />
</Navbar.Header>
<Navbar.Collapse className="bs-navbar-collapse">
<Nav>
<NavItem eventKey={1} href="/">Home</NavItem>
</Nav>
<Nav pullRight>
<NavItem eventKey={1} href="/join">Sign Up</NavItem>
<NavItem eventKey={2} href="/login">Login</NavItem>
</Nav>
</Navbar.Collapse>
</Navbar>
)
}
}
The code for my server is as follows:
// module imports
import express from 'express';
import http from 'http';
// react imports
import React from 'react';
import { renderToString } from 'react-dom/server';
import { match, RoutingContext } from 'react-router';
// route imports
import { routes } from './lib/routes';
const app = express();
app.use(express.static('public'));
app.set('views', __dirname + '/public/views');
app.set('view engine', 'ejs');
app.get('*', (req, res) => {
match({ routes, location: req.url }, (err, redirectLocation, props) => {
if (err) {
res.status(500).send(err.message);
} else if (redirectLocation) {
res.redirect(302, redirectLocation.pathname + redirectLocation.search);
} else if (props) {
const markup = renderToString(<RoutingContext {...props} />);
res.render('index', { markup })
} else {
res.sendStatus(404);
}
});
});
const server = http.createServer(app);
server.listen(3000);
server.on('listening', () => {
console.log('Listening on 3000');
});
I've been using routes like the following, and I learned this via a great tutorial from Egghead.io
Live demo: http://ec2-52-91-0-209.compute-1.amazonaws.com
Demo repo: https://github.com/mikechabot/material-ui-hello-world
App.js (main entry)
import React from 'react';
import ReactDOM from 'react-dom';
import { Router } from 'react-router';
import routes from './config/routes.jsx';
ReactDOM.render(
<Router>{routes}</Router>,
document.getElementById('my-app')
);
./config/routes.jsx
import React from 'react';
import Main from '../components/Main';
import Index from '../components/Index';
import { Route, IndexRoute } from 'react-router';
export default (
<Route path="/" component={Main}>
<IndexRoute component={Index} />
</Route>
)
../components/Main.jsx
import React from 'react';
class Main extends React.Component {
render() {
return (
<div>
Hello World. Display my children:
{this.props.children}
</div>
);
}
}
export default Main;
../components/Index.jsx
import React from 'react';
class Index extends React.Component {
render() {
return (
<div>
I'm the index Route
</div>
);
}
}
export default Index ;
Related
I tried to create an authentication website with Firebase using email and password. I can't even load the Login page.
Here's Auth.js
import React, { useState, useEffect} from "react";
import { auth } from './config'
import { onAuthStateChanged } from "firebase/auth";
export const AuthContext = React.createContext();
export const AuthProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
useEffect(() => {
onAuthStateChanged(auth, (user) => {
setCurrentUser(user);
})
}, [])
return (
<AuthContext.Provider value={{currentUser}}>
{children}
</AuthContext.Provider>
)
}
And this is Login.js
import React, {useContext ,useState } from "react";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
import "./Login.css";
import { auth } from './config'
import { signInWithEmailAndPassword } from "firebase/auth";
import { AuthContext } from "./Auth";
import { useHistory } from "react-router-dom";
const Login = () => {
let history = useHistory();
const handleSubmit = (event) => {
event.preventDefault();
const { email, password } = event.target.elements;
signInWithEmailAndPassword(auth, email.value, password.value)
.then((userCredential) => {
const user = userCredential.user;
console.log(user.uid);
})
.catch((error) => {
console.log(error.massage);
});
}
const currentUser = useContext(AuthContext);
if(currentUser) {
return history.push('/dashboard');
}
return (
<div className="Login">
<h1>Login</h1>
<Form onSubmit={handleSubmit}>
//Login Form
</Form>
</div>
);
}
export default Login
And DashBoard.js
import React, {useContext} from 'react'
import { AuthContext } from './Auth'
import { auth } from './config'
import { signOut } from 'firebase/auth'
import { useHistory } from "react-router-dom";
const DashBoard = () => {
const currentUser = useContext(AuthContext);
let history = useHistory();
if(!currentUser) {
return history.push('/login');
}
const signOutFunc = () => {
signOut(auth)
}
return (
<div>
<div className='container mt-5'>
<h1>Welcome</h1>
<h2>If you see this you are logged in.</h2>
<button className='btn btn-danger' onClick={signOutFunc}>Sign Out</button>
</div>
</div>
)
}
export default DashBoard;
Lastly App.js
import { BrowserRouter as Router, Route, Switch} from 'react-router-dom'
import Login from './Login'
import DashBoard from './DashBoard';
import { AuthProvider } from './Auth'
function App() {
return (
<AuthProvider>
<Router>
<Switch>
<Route exact path="/login" component={Login} />
<Route exact path="/dashboard" component={Dashboard} />
</Switch>
</Router>
</AuthProvider>
);
}
export default App;
When I open /login, it would send me to /dasgboard immediately. If I typed /login again it gives me this error
Error: Login(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
I can't figure it out what's wrong with it. Please help me.
Thank you
You have multiple places in your code where you return history.push('/dashboard'); or another path. You should return there a null:
if(!currentUser) {
history.push('/login');
return null
}
i was new in ionic and angular i want small project for testing in ionic that upload image by post method and nodejs express file images....
but when i run displayed error for [uploader] in my input...
there is my code of home.html
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title>
Home
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<div class="container">
<input type="file" name="photo" ng2FileSelect [uploader]="uploader" />
<button type="button" class="btn btn-success btn-s"
(click)="uploader.uploadAll()"
[disabled]="!uploader.getNotUploadedItems().length" >
Upload an Image
</button>
</div>
<ion-card>
<ion-card-header>
<img src="http://localhost:3000/images/home.jpg" alt="">
</ion-card-header>
</ion-card>
</ion-content>
and this my home.ts
import { Component } from '#angular/core';
import { HttpClient, HttpEventType } from '#angular/common/http';
// import {DomSanitizer} from '#angular/platform-browser';
import { FileUploader, FileSelectDirective } from 'ng2-file-upload';
const URL = 'http://localhost:3000/images/';
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
title = 'ng8fileupload';
public uploader: FileUploader = new FileUploader({ url: URL,
itemAlias: 'photo' });
public db: any;
public image: any;
base64Image;
fileData: File = null;
constructor(private http: HttpClient,) {
}
ngOnInit() {
this.uploader.onAfterAddingFile = (file) => { file.withCredentials
= false; };
this.uploader.onCompleteItem = (item: any, response: any, status:
any, headers: any) => {
console.log('ImageUpload:uploaded:', item, status, response);
alert('File uploaded successfully');
};
}
}
and this is my app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { RouteReuseStrategy } from '#angular/router';
import { IonicModule, IonicRouteStrategy } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { FileSelectDirective, FileUploadModule } from 'ng2-file-
upload';
import { FormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '#angular/common/http';
#NgModule({
declarations: [
AppComponent
],
entryComponents: [],
imports: [
BrowserModule,
HttpClientModule,
FileUploadModule,
FormsModule,
IonicModule.forRoot(),
AppRoutingModule,
],
providers: [
StatusBar,
SplashScreen,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule {}
and this serverside
const path = require('path');
const express = require('express');
const multer = require('multer');
const bodyParser = require('body-parser')
const app = express();
const DIR = '/images';
let storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, DIR);
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now() + '.' + path.extname(file.originalname));
}
});
let upload = multer({storage: storage});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8100');
res.setHeader('Access-Control-Allow-Methods', 'POST');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-
With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.get('/api', function (req, res) {
res.end('file catcher example');
});
app.post('/api/upload',upload.single('photo'), function (req, res) {
if (!req.file) {
console.log("No file received");
return res.send({
success: false
});
} else {
console.log('file received');
return res.send({
success: true
})
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, function () {
console.log('Node.js server is running on port ' + PORT);
});
please help me
Inside your home.ts file component decorator add the directive for the file Uploader package you have used. It is shown below:
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
directives: [FILE_UPLOAD_DIRECTIVES]
})
Also change the import line as mentioned below:
import { FileUploader, FILE_UPLOAD_DIRECTIVES } from 'ng2-file-upload';
Also change the import line in app.module.ts as well!
I am sure this should work!
I have created a e Commerce App in react. As you can see from the screenshot below, that when I click on the Apparels->Girls->Shoes , the data is not displayed in the screen.
So first, in the index.js file, I have set the BrowserRouter and created a component Main which holds all my other components.
index.js
import React from "react";
import ReactDOM from "react-dom";
import Main from "./Main";
import "./index.css";
import 'bootstrap/dist/css/bootstrap.css';
import {Route, NavLink, BrowserRouter} from 'react-router-dom';
ReactDOM.render((
<BrowserRouter>
<Main/>
</BrowserRouter>
)
,
document.getElementById("root")
);
After this I have created Main.js, where I have created components for Navigation and PLPMenu( which should display after clicking on the Girls->Shoes). Also in the Main.js, I have set the switch and Route paths
Main.js
import React, { Component } from "react";
import 'bootstrap/dist/css/bootstrap.min.css';
import { Route, Switch } from 'react-router-dom';
import Navigation from "./components/topNavigation";
import Footer from "./components/Footer";
import Banner from "./components/Banner";
import PLPMenu from "./components/PLPMenu";
import PDP from "./components/PDP";
import Home from "./components/Home";
class Main extends Component {
render() {
return (
<div>
<Navigation />
<Switch>
<Route exact path="/" component={Home} />
<Route path="Apparel/Girls/:id" component={PLPMenu}/>
<Route path="/PDP" component={PDP} />
<Route path="/Banner" component={Banner} />
<Route path="/Footer" component={Footer} />
</Switch>
</div>
)
}
}
export default Main;
In the topNavigation.js, I'm displaying the first level of categories like Apparel, Electronics, Grocery etc. Also, I have created, a component SubMenu for displaying the second level of categories like Girls, Boys, Women etc.
topNavigation.js
import React, { Component } from 'react';
import axios from 'axios';
import SubMenu from './subMenu';
class Navigation extends Component {
state = {
mainCategory: []
}
componentDidMount() {
axios.get('http://localhost:3030/topCategory')
.then(res => {
console.log(res.data.express);
this.setState({
mainCategory: res.data.express.catalogGroupView
})
})
}
render() {
const { mainCategory } = this.state;
return mainCategory.map(navList => {
return (
<ul className="header">
<li key={navList.uniqueID}>
<a className="dropbtn ">{navList.name} </a>
<ul className="dropdown-content">
<SubMenu below={navList.catalogGroupView} />
</ul>
</li>
</ul>
)
})
}
}
export default Navigation;
subMenu.js
In the submenu.js, I have created one more component SubListMenu for displaying the inner categories like Shoes, Pants, Skirts, Tops etc.
import React, { Component } from 'react';
import SubListMenu from './subListMenu';
class SubMenu extends Component {
render() {
const { below } = this.props;
return below.map(sub => {
return (
<React.Fragment>
<li key={sub.uniqueID}>
<a>{sub.name}</a>
{
<ul className="sub-menu">
{sub.catalogGroupView !== undefined && <SubListMenu id={sub.uniqueID} subBelow={sub.catalogGroupView} />}
</ul>
}
</li>
</React.Fragment>
)
})
}
}
export default SubMenu;
subListMenu.js
import React, { Component } from 'react';
import {Link} from 'react-router-dom';
class SubListMenu extends Component {
render() {
const { subBelow, id } = this.props;
console.log(subBelow)
return(
<React.Fragment>
{subBelow && subBelow.map(subl => {
return (
<li key={subl.uniqueID}><Link to = {`Apparel/Girls/${subl.name}/${ subl.uniqueID }`}>{subl.name}</Link></li>
)
})
}
</React.Fragment>
)
}
}
export default SubListMenu;
As you can see from my subListMenu.js code, that I have set the Link to PLPMenu.js. But in my case it's not happening. Also, the part Apparel/Girls in the Link, I have hard coded which i'm not able to make it dynamic.
PLPMenu.js
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
class PLPMenu extends Component {
state = {
shoeCategory: []
}
componentDidMount() {
let pathname= this.props.match.params.id
console.log(pathname)
axios.get(`http://localhost:3030/${pathname}`)
.then(res => (res.json()))
.then(data => {
this.setState({
shoeCategory: data.express.catalogEntryView
})
});
}
render() {
const { shoeCategory } = this.state;
const picUrl = 'https://149.129.128.3:8443'
return (
<div>
<div className="container">
<div className="row">
{
shoeCategory && shoeCategory.map(shoeList => (
<div className="col-md-4">
<h2 key={shoeList.uniqueID}></h2>
<img src={picUrl + shoeList.thumbnail} />
<Link to="/PDP"><p className="pdp">{shoeList.name}</p></Link>
<p>Price : {shoeList.price[0].value} {shoeList.price[0].currency}</p>
</div>
))
}
</div>
</div>
</div>
)
}
}
export default PLPMenu;
For fetching the data, I have used a node server.
server.js
const express = require('express');
const cors = require('cors');
const Client = require('node-rest-client').Client;//import it here
const app = express();
app.use(cors());
app.get('/topCategory', (req, res) => {
var client = new Client();
// direct way
client.get("http://149.129.128.3:3737/search/resources/store/1/categoryview/#top?depthAndLimit=-1,-1,-1,-1", (data, response) => {
res.send({ express: data });
});
});
app.get('/GirlShoeCategory', (req, res) => {
var client = new Client();
// direct way
client.get("http://149.129.128.3:3737/search/resources/store/1/productview/byCategory/10015", (data, response) => {
res.send({ express: data });
});
});
const port = 3030;
app.listen(port, () => console.log(`Server running on port${port}`));
I don't know where my code is getting wrong. Maybe I feel that from the node server, there is a mismatch with the reactjs routes, for which only in the url, it's displaying the link but not the contents. Can someone please give me an insight on this. My console browser window:
for this issue
In the PLPMenu.js page, I'm trying to fetch the data. But all I'm getting is this undefined.
componentDidMount() {
let pathname= this.props.match.params.id
console.log(this.props.match.params.id)
axios.get(`http://localhost:3030/${pathname}`)
.then(res => {return res.json();})
.then(data => {
this.setState({
shoeCategory: data.express.catalogEntryView
})
});
}
try this it will solve undefined issue.
I believe you have to take id from subBelow instead this.props.id.
so change the code like this.
<li key={subl.uniqueID}><Link to = {`Apparel/Girls/${ subl.uniqueID }`}>{subl.name}</Link></li>
The reason you get undefined in URL bar because you are not passing the unique id from SubMenu down to SubListMenu component.
What you need to do is
SubMenu.js
import React, { Component } from 'react';
import SubListMenu from './subListMenu';
class SubMenu extends Component {
render() {
const { below } = this.props;
return below.map(sub => {
return (
<React.Fragment>
<li key={sub.uniqueID}>
<a>{sub.name}</a>
{
<ul className="sub-menu">
{sub.catalogGroupView !== undefined && <SubListMenu id={sub.uniqueID} subBelow={sub.catalogGroupView} />}
</ul>
}
</li>
</React.Fragment>
)
})
}
}
export default SubMenu;
SubListMenus.js
import React, { Component } from 'react';
import {Link} from 'react-router-dom';
class SubListMenu extends Component {
render() {
const { subBelow, id } = this.props;
console.log(subBelow)
return(
<React.Fragment>
{subBelow && subBelow.map(subl => {
return (
<li key={subl.uniqueID}><Link to = {`Apparel/Girls/${ id }`}>{subl.name}</Link></li>
)
})
}
</React.Fragment>
)
}
}
export default SubListMenu;
Regarding below issue You need to do res.json() and in next .then get the data
In the PLPMenu.js page, I'm trying to fetch the data. But all I'm getting is this undefined.
Do this
componentDidMount() {
let pathname= this.props.match.params.id
console.log(this.props.match.params.id)
axios.get(`http://localhost:3030/${pathname}`)
.then(res => (res.json()))
.then(data => {
this.setState({
shoeCategory: data.express.catalogEntryView
})
});
}
Edit:
Add below condition in PLPMenu component
{shoeCategory && shoeCategory.map(shoeList => (
I have got a simple react-router-redux application going on where /home has a button which when clicked should navigate to /profile page. Currently my code looks like this.
actions/index.js
import { push } from 'react-router-redux'
import * as actionTypes from '../constants'
const homeClicked = () => {
return { type: actionTypes.HOME_CLICK }
}
const profileClicked = () => {
return { type: actionTypes.PROFILE_CLICK }
}
export const handleHomeClick = () => {
return (dispatch) => {
dispatch(homeClicked())
dispatch(push('/profile'))
}
}
export const handleProfileClick = () => {
return (dispatch) => {
dispatch(profileClicked())
dispatch(push('/'))
}
}
containers/HomeContainer.js
import React from 'react'
import { connect } from 'react-redux'
import * as actions from '../actions'
import { withRouter } from 'react-router-dom'
import PropTypes from 'prop-types'
class Home extends React.Component {
handleClick = () => {
this.props.handleHomeClick();
}
render() {
return (
<div className='Home'>
<button onClick={this.handleClick}>Home</button>
</div>
)
}
}
Home.propTypes = {
handleHomeClick: PropTypes.func.isRequired
}
const mapStateToProps = () => {
return {}
}
export default withRouter(connect(mapStateToProps, actions)(Home))
containers/ProfileContainer.js
import React from 'react'
import { connect } from 'react-redux'
import * as actions from '../actions'
import { withRouter } from 'react-router-dom'
import PropTypes from 'prop-types'
class Profile extends React.Component {
handleClick = () => {
this.props.handleProfileClick();
}
render() {
return (
<div className='Profile'>
<button onClick={this.handleClick}>Profile</button>
</div>
)
}
}
Profile.propTypes = {
handleProfileClick: PropTypes.func.isRequired
}
const mapStateToProps = () => {
return {}
}
export default withRouter(connect(mapStateToProps, actions)(Profile))
reducers/index.js
import { HOME_CLICK, PROFILE_CLICK } from '../constants'
import { combineReducers } from 'redux'
import { routerReducer } from 'react-router-redux'
const clickReducer = (state={ message: 'HOME' }, action) => {
switch(action.type) {
case HOME_CLICK:
return { message: 'PROFILE' };
case PROFILE_CLICK:
return { message: 'HOME' };
default:
return state
}
}
export default combineReducers({
clicking: clickReducer,
routing: routerReducer
})
constants.js
export const HOME_CLICK = 'HOME_CLICK'
export const PROFILE_CLICK = 'PROFILE_CLICK'
history.js
import { createBrowserHistory } from 'history'
export default createBrowserHistory()
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux';
import createRoutes from './routes'
import rootReducer from './reducers'
import thunk from 'redux-thunk'
import browserHistory from './history'
import reduxLogger from 'redux-logger'
import { createStore, applyMiddleware } from 'redux'
import { syncHistoryWithStore, routerMiddleware } from 'react-router-redux';
const middlewares = applyMiddleware(
thunk,
routerMiddleware(browserHistory),
reduxLogger
);
const store = createStore(rootReducer, middlewares)
const history = syncHistoryWithStore(browserHistory, store)
const routes = createRoutes(history)
ReactDOM.render(
<Provider store={store}>
{routes}
</Provider>,
document.getElementById('root')
)
routes.js
import React from 'react'
import { Router, Route, Switch } from 'react-router'
import HomeContainer from './containers/HomeContainer'
import ProfileContainer from './containers/ProfileContainer'
const createRoutes = (history) => {
return (
<Router history={history}>
<Switch>
<Route exact path='/' component={HomeContainer}/>
<Route path='/profile' component={ProfileContainer}/>
</Switch>
</Router>
)
}
export default createRoutes
app.js
import express from 'express'
import config from './config'
import path from 'path'
const app = express()
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')))
app.get('*', (req, resp) => {
resp.render('index');
})
app.listen(config.port, config.host, () => {
console.info('Server listening to', config.serverUrl())
})
This code is changing the url but not rendering the profile page when the home button on the home page is clicked. Also here's a link of the picture of redux logger output.
I am stuck on this for a few hours and other SO answers have not been much of a help. Any help would be appreciated.
When you click home it should render the home route as you have it written now? Isn't that what it is supposed to do.
I'm trying to server-render content for my app that uses react-router v4,redux, and express but I get Browser history needs a DOM error in the terminal. I also use react-router-config to keep my routes more organized. Saw a solution that suggested that one should create the store on the server, so I tried copypasting the code from store.js file to the server, however it didn't work out. What can I do to fix this extremely unpleasant error?
routes.js
const routes = (
{
component: App,
routes: [
{
path: '/',
exact:true,
component: Home
},
{
path: '/login',
exact:true,
component: Login
},
{
path: '/registration',
exact:true,
component: Registration
},
{
path: '/person/:id',
exact:true,
component: UserPage
},
{
path: '/myPage',
exact:true,
component: MyPage
},
{
path: '/goodBye',
exact:true,
component: GoodBye
},
{
path: '*',
component: NoMatch
}
]
}
);
App.js
import React from 'react';
import ReactDOM from 'react-dom';
//import '../styles/app.scss'
import {Provider} from 'react-redux';
import {Grid} from 'react-bootstrap';
import store from './store/store';
import routes from './routes';
import { createBrowserHistory } from 'history';
import { syncHistoryWithStore } from 'react-router-redux';
import { renderRoutes } from 'react-router-config';
import { BrowserRouter as Router} from 'react-router-dom';
import { ConnectedRouter, Switch } from 'connected-react-router';
class App extends React.Component {
render() {
return (
<Provider store={store}>
<Grid fluid={true}>
<ConnectedRouter history={createBrowserHistory()}>
<Switch>
{renderRoutes(routes)}
</Switch>
</ConnectedRouter>
</Grid>
</Provider>
);
}
}
const isBrowser = typeof window !== 'undefined';
if(isBrowser) {
ReactDOM.render(<App/>, document.getElementById('root'));
}
Route handler:
import express from 'express';
import React, {Component} from 'react';
import { renderToString } from 'react-dom/server';
import routes from '../../js/routes';
import {StaticRouter} from 'react-router';
import { renderRoutes } from 'react-router-config';
import { Provider } from 'react-redux';
import store from '../../js/store/store';
const router = express.Router();
router.get('*',(req,res) => {
let context = {};
const content = renderToString(
<Provider store={store}>
<StaticRouter location={req.url} context={context}>
{renderRoutes(routes)}
</StaticRouter>
</Provider>
);
if(context.status === 404) {
res.status(404);
}
res.render('index', {title: 'Express', data: store.getState(), content });
});