React Universal pass data to component - reactjs

Hi I am brand new in react. I am trying to pass data from server to client via React universal rendering. But I am in now luck. Still I can render the html but I am not able to access data through this.props.data
Here is my code
// server.js
app.get('*', (req, res) => {
match({
routes: (<Router>{routes}</Router>),
location: req.url
},
(err, redirect, renderProps) => {
if (err) {
return res.status(500).send(err.message);
} else if (redirect) {
return res.redirect(302, redirect.pathnam + redirect.search);
} else if (renderProps.components.some(component => component === NotFoundPage)) {
res.status(404);
}
let data = [
{
title: 'Godfather'
},
{
title: 'Godfather 2'
}
];
data = JSON.stringify(data);
const renderedApp = renderToString(
<DataWrapper data={data}>
<RouterContext {...renderProps} />
</DataWrapper>
);
res.render('index.ejs', {
renderedApp
});
});
});
// routes.js
import React from 'react';
import { Route, IndexRoute } from 'react-router';
import HomePage from './components/routes/HomePage';
import MovieDetailsPage from './components/routes/MovieDetailsPage';
import NotFoundPage from './components/routes/NotFoundPage';
import App from './components/app';
export {
NotFoundPage
};
export default (
<Route path="/">
<IndexRoute component={HomePage} />
<Route path="movie" component={MovieDetailsPage} />
<Route path="*" component={NotFoundPage} />
</Route>
);
// client.js
import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, browserHistory } from 'react-router';
import routes from './routes';
import DataWrapper from '../src/DataWrapper';
let data = [];
ReactDOM.render(
<DataWrapper data={data}>
<Router history={browserHistory} routes={routes} onUpdate={window.scrollTo(0, 0)}/>
</DataWrapper>,
document.getElementById('app')
);
// DataWrapper
import React, { Component } from 'react';
class DataWrapper extends Component {
getChildContext () {
return {
data: this.props.data
};
}
render () {
return this.props.children;
}
}
DataWrapper.childContextTypes = {
data: React.PropTypes.oneOfType([
React.PropTypes.object,
React.PropTypes.array
]).isRequired
};
export default DataWrapper;
// HomePage.js where I want to access the data in this.props.data
import React, { Component } from 'react';
export default class HomePage extends Component {
constructor(props) {
super(props);
this.state = {
data: this.props.data
};
}
render() {
return (
<div>
<h1>{this.state.data}</h1>
</div>
);
}
}
Can someone please point me in the right direction and explain if possible what I am doing wrong
Thank you

You're currently rendering the children in DataWrapper, but you're not passing in the props.
Not sure if this is the optimal way to do this, but here's how I get the props and state passed in
{this.props.children && React.cloneElement(this.props.children, {
state: this.state
})}

In this use case, I suggest using Redux instead of writing the custom data wrapper. Because
Redux can make the single source of truth, all the components can refer to that, no matter which level it's in (parent or childen) and where is the page rendered (server or client). It can help you to make the architect clearer even it introduces more overhead.
Here's some pseudo code I used before:
// server.js
// configureStore will create a empty store here.
const store = configureStore();
// Then use store.setState or any middleware to prepopulate the store.
....
const jsx = (
<ReduxProvider store={store}>
<StaticRouter context={context} location={req.url}>
<App/>
</StaticRouter>
</ReduxProvider>
);
const html = '<!doctype html><html><head></head>
<body>
<script>
window.REDUX_DATA = ${ JSON.stringify(store.getState()) }
</script>
<div id="root">${ReactDOM.renderToString(jsx)}</div>
</body>
</html>'
res.send(html)
//client.js
const render = App => {
// configStore will create store in client side with initial state passed from server.
const store = configStore(window.REDUX_DATA);
return ReactDOM.hydrate(
<ReduxProvider store={store}>
<BrowserRouter>
<App/>
</BrowserRouter>
</ReduxProvider>,
document.getElementById('root')
);
};
//HomePage.js
class HomePage extends React.Component {
render() {
return (
<div>
this.props.foo.value
</div>
)
}
const mapStateToProps = (state) => ({foo: state.foo});
export default connect(mapStateToProps)(HomePage);
}

Related

React Router not rendering component initially

This is weird one for me. I start my app up locally. I just have a Header and TaskPage in my App like so.
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import Header from '../components/header';
import TasksPage from '../pages/tasks';
import { Route } from 'react-router';
class App extends Component {
render() {
return (
<div>
<Header />
<main>
<Route exact path="/" component={TasksPage} />
</main>
</div>
);
}
}
export default withRouter(connect()(App));
And then my router stuff.
import './views/styles/styles.css';
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import history from './history';
import configureStore from './store';
import registerServiceWorker from './utils/register-service-worker';
import App from './views/app';
import TaskPage from './views/pages/tasks'
const store = configureStore();
const rootElement = document.getElementById('root');
function render(Component) {
console.log('COMPONENT::',Component);
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<div>
<Component />
</div>
</ConnectedRouter>
</Provider>,
rootElement
);
}
if (module.hot) {
module.hot.accept('./views/app', () => {
render(require('./views/app').default);
})
}
registerServiceWorker();
I initially get a blank page. But if I make a change to the App page and save it while the app is running, like just a space or line return, something insignificant, I get my tasks page suddenly. It works fine then. I have no errors in my console at any point during this process so I think I have something wrong with my routing somewhere when the app initially loads.
Or maybe it has something to do with this TaskPage.
import React, { Component } from 'react';
import { List } from 'immutable';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import { createSelector } from 'reselect';
import { getTaskFilter, getVisibleTasks, tasksActions } from 'src/tasks';
import TaskFilters from '../../components/task-filters';
import TaskForm from '../../components/task-form';
import TaskList from '../../components/task-list';
export class TasksPage extends Component {
static propTypes = {
createTask: PropTypes.func.isRequired,
filterTasks: PropTypes.func.isRequired,
filterType: PropTypes.string.isRequired,
loadTasks: PropTypes.func.isRequired,
location: PropTypes.object.isRequired,
removeTask: PropTypes.func.isRequired,
tasks: PropTypes.instanceOf(List).isRequired,
updateTask: PropTypes.func.isRequired
};
componentWillMount() {
this.props.loadTasks();
this.props.filterTasks(
this.getFilterParam(this.props.location.search)
);
}
componentWillReceiveProps(nextProps) {
if (nextProps.location.search !== this.props.location.search) {
this.props.filterTasks(
this.getFilterParam(nextProps.location.search)
);
}
}
componentWillUnmount() {
// this.props.unloadTasks();
}
getFilterParam(search) {
const params = new URLSearchParams(search);
return params.get('filter');
}
render() {
return (
<div className="g-row">
<div className="g-col">
<TaskForm handleSubmit={this.props.createTask} />
</div>
<div className="g-col">
<TaskFilters filter={this.props.filterType} />
<TaskList
removeTask={this.props.removeTask}
tasks={this.props.tasks}
updateTask={this.props.updateTask}
/>
</div>
</div>
);
}
}
//=====================================
// CONNECT
//-------------------------------------
const mapStateToProps = createSelector(
getTaskFilter,
getVisibleTasks,
(filterType, tasks) => ({
filterType,
tasks
})
);
const mapDispatchToProps = Object.assign(
{},
tasksActions
);
export default withRouter(connect(
mapStateToProps,
mapDispatchToProps
)(TasksPage));
So something with the hotloading or maybe the way I had it setup?? Im not saying its the best answer but it did resolve my problem. If someone can explain this better than I'll happily accept a clearer response on the subject
This should have worked based on the docs. But I commented it out and went back to just using ReactDOM.Render with my . No wrapped Function or . And oddly hotloading still seems to work.
// function render(Component) {
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<div>
<App/>
</div>
</ConnectedRouter>
</Provider>,
rootElement
);
// }
// if (module.hot) {
// module.hot.accept('./views/app', () => {
// render(require('./views/app').default);
// })
// }
FYI - Im react-router 4.x, Redux 5.x, React 15.x.

React Router v4 and loadable-components always rendering same Component even though the route matches other

I've got a Standard React-Redux Application with react router v4, webpack 4 and I'm trying to perform lazy loading of components via loadable-components library, so webpack can create chunks and load them on demand. The problems seems it's always rendering the Dashboard (refer code below) Component inside the <Switch>, no matter the route.
I don't understand the cause. I found a similar problem: React-Router v4 rendering wrong component but matching correctly but it follows a different pattern and I can't or don't understand how to apply that solution into my issue.
I'm posting The main AppContainer and the routes file:
AppContainer.js:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Provider } from 'react-redux'
import ReduxToastr from 'react-redux-toastr'
import 'react-redux-toastr/src/styles/index.scss'
import { Offline, Online } from 'react-detect-offline'
import Footer from 'components/Footer/'
import { Modal, ModalHeader, ModalBody } from 'reactstrap'
import { Translate } from 'react-redux-i18n'
import { PersistGate } from 'redux-persist/integration/react'
import { Router, Switch, Route } from 'react-router-dom'
import PrivateRoute from 'components/PrivateRoute'
import { Dashboard, PasswordReset, PasswordResetEdit, SignIn } from 'routes'
// Layout
import CoreLayout from 'layouts/CoreLayout'
class AppContainer extends Component {
static propTypes = {
history: PropTypes.object.isRequired,
persistor: PropTypes.object.isRequired, // redux-persist
store : PropTypes.object.isRequired
}
render () {
const { history, store, persistor } = this.props
const opened = true
const toastrDefaultTimeout = 8000
const newToastrAlwaysOnTop = false
return (
<div>
<Online>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<div style={{ height: '100%' }}>
<ReduxToastr
timeOut={toastrDefaultTimeout}
newestOnTop={newToastrAlwaysOnTop}
preventDuplicates
position='top-right'
transitionIn='fadeIn'
transitionOut='fadeOut'
progressBar />
<Router history={history}>
<CoreLayout {...this.props} >
<Switch>
<Route exact path='/sign-in' component={SignIn} />
<Route exact path='/passwords/new' component={PasswordReset} />
<Route exact path='/passwords/edit' component={PasswordResetEdit} />
<PrivateRoute exact path='/' component={Dashboard} persistor={persistor} />
</Switch>
</CoreLayout>
</Router>
</div>
</PersistGate>
</Provider>
</Online>
<Offline>
<div className='app'>
<div className='app-body'>
<main className='main align-items-center align-self-center'>
<div className='container'>
<div className='animated fadeIn'>
<Modal isOpen={opened} toggle={this.toggle}>
<ModalHeader toggle={this.toggle}><Translate value={`views.shared.no-internet.title`} /></ModalHeader>
<ModalBody>
<div className='card-block'>
<div className='row'>
<div className='col-sm-12'>
<Translate value='views.shared.no-internet.description' />
</div>
</div>
</div>
</ModalBody>
</Modal>
</div>
</div>
</main>
</div>
<Footer />
</div>
</Offline>
</div>
)
}
}
export default AppContainer
routes/index.js:
// We only need to import the modules necessary for initial render
import loadable from 'loadable-components'
import { hot } from 'react-hot-loader'
// Component split-code (lazy load)
let Dashboard,
SignIn,
PasswordReset,
PasswordResetEdit
// Needed for HMR
if (__DEV__) {
Dashboard = hot(module)(loadable(() => import('./Dashboard')))
PasswordReset = hot(module)(loadable(() => import('./PasswordReset')))
PasswordResetEdit = hot(module)(loadable(() => import('./PasswordResetEdit')))
SignIn = hot(module)(loadable(() => import('./SignIn')))
} else {
Dashboard = loadable(() => import('./Dashboard'))
SignIn = loadable(() => import('./SignIn'))
PasswordReset = loadable(() => import('./PasswordReset'))
PasswordResetEdit = loadable(() => import('./PasswordResetEdit'))
}
export { Dashboard, PasswordReset, PasswordResetEdit, SignIn }
And for anyone curious, here is the PrivateRoute component:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Route, Redirect } from 'react-router-dom'
import { connect } from 'react-redux'
import { validateSession } from 'modules/sessions/session'
const mapStateToProps = state => ({
session: state.session
})
const mapDispatchToProps = (dispatch) => {
return {
validateSession: () => { dispatch(validateSession()) }
}
}
class PrivateRoute extends Component {
componentDidMount () {
this.props.validateSession(this.props.persistor)
}
render () {
const { component: Component, session, ...rest } = this.props
return (
<Route {...rest} render={(routeProps) =>
this.props.session.userSignedIn ? <Component {...routeProps} />
: <Redirect to={{
pathname: '/sign-in',
state: { from: routeProps.location }
}} />
}
/>)
}
}
PrivateRoute.propTypes = {
component: PropTypes.func.isRequired,
persistor: PropTypes.object.isRequired,
session: PropTypes.object.isRequired,
validateSession: PropTypes.func.isRequired
}
export default connect(mapStateToProps, mapDispatchToProps)(PrivateRoute)
If I remove the if (_DEV_) block in routes/index.js and always do it like the 'else' block everything works okay, however I lose HMR, meaning I have to refresh the browser to see code changes take effect.
Edit
For anyone wandering where the history prop comes from:
Main app entry point (in webpack.config.js). src/main.js:
import React from 'react'
import ReactDOM from 'react-dom'
import createStore from './store/createStore'
import { hot } from 'react-hot-loader'
import AppContainer from './containers/AppContainer'
import { persistStore } from 'redux-persist'
// ========================================================
// Store Instantiation
// ========================================================
const initialState = window.___INITIAL_STATE__
const { history, store } = createStore(initialState)
// begin periodically persisting the store
let persistor = persistStore(store)
// ========================================================
// Render Setup
// ========================================================
const MOUNT_NODE = document.getElementById('root')
let render = () => {
ReactDOM.render(
<AppContainer store={store} persistor={persistor} history={history} />,
MOUNT_NODE
)
}
// This code is excluded from production bundle
if (__DEV__) {
if (module.hot) {
// Development render functions
const renderApp = render
const renderError = (error) => {
const RedBox = require('redbox-react').default
ReactDOM.render(<RedBox error={error} />, MOUNT_NODE)
}
// Wrap render in try/catch
render = () => {
try {
renderApp()
} catch (error) {
console.error(error)
renderError(error)
}
}
// Setup hot module replacement
module.hot.accept('./containers/AppContainer', () =>
render(require('./containers/AppContainer').default)
)
}
}
// ========================================================
// Go!
// ========================================================
export default hot(module)(render)
render()
createStore.js:
import { applyMiddleware, compose, createStore } from 'redux'
import thunk from 'redux-thunk'
import { apiMiddleware } from 'redux-api-middleware'
import { createLogger } from 'redux-logger'
import makeRootReducer from './reducers'
import { routerMiddleware } from 'react-router-redux'
// I18n
import { syncTranslationWithStore, loadTranslations, setLocale } from 'react-redux-i18n'
import { translationsObject } from 'translations/index'
// Router history
import createHistory from 'history/createBrowserHistory'
// Raven for Sentry
import Raven from 'raven-js'
import createRavenMiddleware from 'raven-for-redux'
export default (initialState = {}) => {
// ======================================================
// Middleware Configuration
// ======================================================
const logger = createLogger()
const history = createHistory()
const historyMiddleware = routerMiddleware(history)
const middleware = [historyMiddleware, apiMiddleware, thunk, logger]
if (__PROD__) {
Raven.config(`${__SENTRY_DSN__}`).install()
middleware.push(createRavenMiddleware(Raven))
}
// ======================================================
// Store Enhancers
// ======================================================
const enhancers = []
let composeEnhancers = compose
const composeWithDevToolsExtension = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
if (typeof composeWithDevToolsExtension === 'function') {
composeEnhancers = composeWithDevToolsExtension
}
// ======================================================
// Store Instantiation and HMR Setup
// ======================================================
const store = createStore(
makeRootReducer(),
initialState,
composeEnhancers(
applyMiddleware(...middleware),
...enhancers
)
)
store.asyncReducers = {}
// DEPRECATED in react-router v4: To unsubscribe, invoke `store.unsubscribeHistory()` anytime
// store.unsubscribeHistory = browserHistory.listen(updateLocation(store))
if (module.hot) {
const reducers = require('./reducers').default
module.hot.accept('./reducers', () => {
store.replaceReducer(reducers(store.asyncReducers))
})
}
syncTranslationWithStore(store)
store.dispatch(loadTranslations(translationsObject))
store.dispatch(setLocale('es_AR'))
return { history, store }
}

onClick navigation in react-router-4

I can not understand what I did incorrect.
Please help.
I need navigate by click to another route in react-route 4.
I saw the similar question here: How to get history on react-router v4?
and made all as in right answer wrote, but React does not render my component.
Bellow is my code:
import history from './history';
const store = createStore(reducer, composeWithDevTools(applyMiddleware()));
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<App />
</Router>
</Provider>,
document.getElementById('root'));
// history.js
import { createBrowserHistory } from 'history'
export default createBrowserHistory({
/* pass a configuration object here if needed */
});
import history from './history';
/**
* onClick function for navigation
*/
onNavigateTask = (id) => {
return () => {
history.push(`/tasks/${id}`);
};
}
the path is correct after click but component is not rendered
//route for component
<Route
path='/task:id'
render={() => {
return (
<CurrentTask
results={results}
/>);
}}
/>
EDITED:
/* eslint-disable no-undef */
import React from 'react';
import PropTypes from 'prop-types';
import { Switch, Route } from 'react-router';
import TimeTracker from './TimeTracker';
import CurrentTask from './CurrentTask';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import { connect } from 'react-redux';
import { initStorage, setStoreItem } from './helpers/localStorage';
import { updateStartTime, updateCurrentTask, updatePickedDay, updateResults } from './actions/TimeTracker';
class App extends React.Component {
constructor () {
super();
initStorage('timeData');
}
render () {
const {
startTime,
currentTask,
firstPickedDay,
secondPickedDay,
results,
onSetStartTime,
onSetCurrentTask,
onSetPickedDay,
onSetResults} = this.props;
return (
<MuiThemeProvider>
<Switch>
<Route
exact path='/'
render={() => {
return (
<TimeTracker
results={results}
startTime={startTime}
currentTask={currentTask}
firstPickedDay={firstPickedDay}
secondPickedDay={secondPickedDay}
onSetStartTime={onSetStartTime}
onSetCurrentTask={onSetCurrentTask}
onSetPickedDay={onSetPickedDay}
onSetResults={onSetResults}
setStoreItem={setStoreItem} />
);
}}
/>
<Route
path='/task:id'
render={() => {
return (
<CurrentTask
results={results}
/>);
}}
/>
</Switch>
</MuiThemeProvider>
);
}
}
export default connect(
state => ({
startTime: state.startTime,
currentTask: state.currentTask,
firstPickedDay: state.firstPickedDay,
secondPickedDay: state.secondPickedDay,
results: state.results
}),
dispatch => ({
onSetStartTime: updateStartTime(dispatch),
onSetCurrentTask: updateCurrentTask(dispatch),
onSetPickedDay: updatePickedDay(dispatch),
onSetResults: updateResults(dispatch)
})
)(App);
App.propTypes = {
startTime: PropTypes.number.isRequired,
currentTask: PropTypes.string.isRequired,
firstPickedDay: PropTypes.number.isRequired,
secondPickedDay: PropTypes.number.isRequired,
results: PropTypes.array.isRequired,
onSetStartTime: PropTypes.func.isRequired,
onSetCurrentTask: PropTypes.func.isRequired,
onSetPickedDay: PropTypes.func.isRequired,
onSetResults: PropTypes.func.isRequired
};
The problem is that the component means that the Router will match the first route and stop. Try changing the order of your routers, so your more specific ones are on top.

React-router first fetch required data, then show current route's component

What's the best way of making sure that my react app has all the data needed when I am using react router? Basically I want to fetch some basic data that are used across whole application, the problem is that when I did it "the easy way" some of my data are fetched twice.
When I enter index route (Dashboard) it first mount this component and fire this.props.fetchAllProjects(), than it mount Loader component and fire this.props.fetchUsersInfo() so it shows just Spinner component and after user info data are fetched id again mount Dashboard and fire this.props.fetchAllProjects() is there any good way of doing this?
Here's my current code:
AppRouter.jsx
<Router history={browserHistory}>
<Route component={Loader}>
<Route path="/" component={MainLayout}>
<IndexRoute components={{ rightSidebar: RightSidebar, main: Dashboard }} />
<Route path="accounts" components={{ rightSidebar: RightSidebar, main: Accounts }} />
</Route>
</Route>
<Route path="*" component={PageNotFound} />
Loader.jsx
import React from 'react';
import { connect } from 'react-redux';
import { fetchUsersInfo } from 'actions/index.actions';
import Spinner from 'components/spinner/Spinner.component';
class Loader extends React.Component {
componentDidMount() {
this.props.fetchUsersInfo();
}
render() {
return (
<div>
{this.props.appState.isFetchingUsersInfo ?
<div>
<Spinner />
</div>
:
<div>
{this.props.children}
</div>
}
</div>
);
}
}
Loader.propTypes = {
children: React.PropTypes.node.isRequired,
appState: React.PropTypes.shape({
isFetchingUsersInfo: React.PropTypes.bool.isRequired,
}),
fetchUsersInfo: React.PropTypes.func.isRequired,
};
const mapStateToProps = state => ({
appState: {
isFetchingUsersInfo: state.appState.isFetchingUsersInfo,
},
});
export default connect(mapStateToProps, { fetchUsersInfo })(Loader);
Dashboard.jsx
import React from 'react';
import { connect } from 'react-redux';
import { fetchAllProjects } from 'actions/index.actions';
import styles from './Dashboard.container.scss';
class Dashboard extends React.Component {
componentDidMount() {
this.props.fetchAllProjects();
}
render() {
return (
<div>
Dashboard
</div>
);
}
}
Dashboard.propTypes = {
appState: React.PropTypes.shape({
isFetchingProjects: React.PropTypes.bool.isRequired,
}),
fetchAllProjects: React.PropTypes.func.isRequired,
};
const mapStateToProps = state => ({
appState: {
isFetchingProjects: state.appState.isFetchingProjects,
},
});
export default connect(mapStateToProps, { fetchAllProjects })(Dashboard);

react render method is called Twice, changing url

I am newbie in react. I read this question , but didn't solve my problem. I think I'm wrong with componentWillReceiveProps comprehension . My component and it's parent are like this:
the parent:
import React from 'react';
import { Router, Route, Link } from 'react-router';
export default class App extends React.Component {
items = [
{id: 1086, title: 'MENU1'},
{id: 1083, title: 'MENU2'},
{id: 1093, title: 'MENU3'}]
renderItems = ()=> {
return this.items.map((item, index)=> {
let url = 'content/' + item.id;
return (<li key={index}><Link to={url} activeClassName="active">{item.title}</Link></li>);
});
}
render() {
return (
<div>
<h1 style={{textAlign:'center'}}>My First React App</h1>
<ul className="nav nav-pills nav-justified">{this.renderItems()}</ul>
{this.props.children}
</div>
);
}
}
the child:
import React, { Component } from 'react';
import UmContent from './UmContent'
import $ from 'jquery';
import ProgressBar from 'progressbar.js';
export default class UmContentContainer extends Component {
state = {
data: ''
}
firstInitial = true;
componentDidMount() {
if (this.firstInitial) {
let props = this.props;
this.sendRequestToServer(props);
this.firstInitial = false;
}
}
sendRequestToServer = (props)=> {
if (!props || !props.params || !props.params.id) {
return;
}
let itemId = props.params.id;
let that = this;
this.setState({data: itemId});
}
componentWillReceiveProps(props, states) {
this.sendRequestToServer(props);
console.log(props.params.id);
}
render() {
return (
<div className="col-md-12">
<h1>{this.state.data}</h1>
</div>);
}
}
and index.js :
import React from 'react'
import { render } from 'react-dom'
import { Router, Route, Link,hashHistory } from 'react-router'
import App from './App';
import UmContentContainer from './Umbreco/UmContentContainer';
render((
<Router history={hashHistory}>
<Route path="/" component={App}>
<Route path="/content/:id" component={UmContentContainer} />
</Route>
</Router>
), document.getElementById('root'))
after first mounting , console writes "id" twice. I can't understand why?
I found my answer HERE , I was wrong , actually it was about the hashHistory and pushing new url . not componentWillReceiveProps.

Resources