my / route doesn't properly render my main component.
Her is my code:
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" componenet={Main}>
<IndexRoute component={Index}></IndexRoute>
<Route path="portfolio" component={Portfolio}></Route>
</Route>
</Router>,
document.getElementById('app')
);
This is my Main component:
export default class Main extends React.Component {
render() {
console.log("asdfasfsaf");
return(
<div>
<h1> This is Main Page </h1>
{this.props.children}
</div>
)
}
}
Once i load the website it doesn't console log anything nor render <h1> This is main page header. Also If I delete this Main componenet it still goes to my IndexRoute without any error which is my index componenet.
Try this:
ReactDOM.render((
<Router history={browserHistory}>
<Route path="/" componenet={Main}>
<IndexRoute component={Index}></IndexRoute>
<Route path="portfolio" component={Portfolio}></Route>
</Route>
</Router>,
), document.getElementById('app'));
Related
I am trying to separate my routes to a separate file using the following code in index.js:
import routes from './routes';
ReactDOM.render(
<Provider store={store}>
<Router routes={routes}/>
</Provider>
, document.getElementById('root')
);
my routes.js looks like this:
export default (
<Switch>
<Route exact path="/" component={AppComponent}/>
<Route exact path="/products" component={ProductContainer}/>
<Route path="/products/:productId" component={AddProductComponent}/>
</Switch>
);
For some reason my page appears blank with this code.
It works perfectly fine if I just wrap all routes inside index.js like this:
ReactDOM.render(
<Provider store={store}>
<Router>
<Switch>
<Route exact path="/" component={AppComponent}/>
<Route exact path="/products" component={ProductContainer}/>
<Route path="/products/:productId" component={AddProductComponent}/>
</Switch>
</Router>
</Provider>
, document.getElementById('root')
);
I would keep it like this, but I would also want to separate into a single file route handling.
Router is just a React component that allows for children prop. Render your routes as a component:
import Routes from './routes';
ReactDOM.render(
<Provider store={store}>
<Router>
<Routes />
</Router>
</Provider>
, document.getElementById('root')
);
Here a sample working codesandbox to play: https://codesandbox.io/s/ywvn59y7rj
More detailed answer, changing routes.js to
class Routes extends React.Component {
render() {
return (
<Switch>
<Route exact path="/" component={AppComponent}/>
<Route exact path="/products" component={ProductContainer}/>
<Route path="/products/:productId" component={AddProductComponent}/>
</Switch>
)
}
}
export default Routes;
and changing index.js to:
ReactDOM.render(
<Provider store={store}>
<Router>
<Routes/>
</Router>
</Provider>
, document.getElementById('root')
);
worked perfectly fine. I hope this would help anybody
Another option wich is easier to maintain is storing routes as JSON like objects in an array and then loop over them.
routes.js
import AppComponent from 'xxx'
export default const routes = [
{
path: '/',
component: AppComponent,
exact: true
}
// and so on
]
index.js
import routes from './routes';
ReactDOM.render(
<Provider store={store}>
<Router>
{routes.map({path, component, exact} => (
<Route exact={exact} path={path} component={component}/>
)}
</Router>
</Provider>
, document.getElementById('root')
);
I have the following on my index.js
<Router routes={routes} />
I would like to have routes section in a separate file, so far I tried this:
routes.js
export default (
<div>
<Route path="/" component={AppComponent}>
<Route path="/someother" component={AddProductComponent} />
</Route>
<Route path="/products" component={ListProductComponent} />
</div>
);
and in index.js
import routes from './routes';
<Router routes={routes} />
For some reason the app shows blank now. looks like the routes are not rendered.
UPDATE, this is my whole index.js except missing imports due stackoverflow companing about too much code put:
const rootReducer = combineReducers({
products: productReducer,
});
const store = createStore(
rootReducer,
applyMiddleware(thunk),
);
ReactDOM.render(
<Provider store={store}>
<Router routes={routes} />
</Provider>
, document.getElementById('root')
);
Update routes.js
export default (
<Switch>
<Route exact path="/" component={AppComponent}/>
<Route path="/products" component={ListProductComponent}>
<Route path="/details/:productId" component={AddProductComponent} />
</Route>
</Switch>
);
You're missing the switch:
<Switch>
<Route path="/someother" component={AppComponent}>
<Route path="/products" component={ListProductComponent} />
<Route path="/" component={AppComponent}>
</Switch>
Also, your code will only show AppComponent, as any url (/, /home, /etc) starts with the slash you put in the path attribute. You might want that as a last page, a fallback.
The path attribute works with a wildcare: path="/" -> path="/**" are functionally the same. If you want an exact path, add exact to the Route.
If you mean to split routes into seperate files, you can do this:
<Switch>
<Route path={"/user"} component={UserRouter}/>
<Route path={"/product"} component={ProductRouter}/>
</Switch>
// In userRouter.jsx:
export function UserRouter() {
return <Switch>
<Route exact path={"/user/list"} component={UserListPage}/>
<Route exact path={"/user/signup"} component={userSignupPage}/>
<Route exact path={"/user/profile"} component={UserProfilePage}/>
</Switch>
};
My Setup:
routes.js
const Router = () => (
<Switch>
<Route path="/" component={ Dashboard } />
<Route path="/somepath" component={ SomePath } />
</Switch>
);
index.js
<HashRouter>
<App />
</HashRouter>
app.js:
lass App extends Component {
render() {
return (
<div className="main-app">
<Header />
<div className="page__container">
<Router />
</div>
<Footer />
</div>
);
}
}
Issue is, when I navigate to localhost/#/ rootpath, it is correctly rendering Dashboard component as mentioned in routes.js file. But When I naviagte to localhost/#/somepath, it not rendering component for somepath, it is stil rendering / Component.
Even in React Devtool it shows <Route path="/"> is loaded, not <Route path="/somepath">
You may have to add exact to match the path. add exact prop to Route
<Route exact path="/somepath" component={ SomePath } />
Sometime I was sawing the well known warning, browser.js:49 Warning: [react-router] You cannot change <Router routes>; it will be ignored and I found two trend issues that friends discussed about this issue and the solution is const routes components and putting them inside Router component.
https://github.com/ReactTraining/react-router/issues/2704
https://github.com/reactjs/react-router-redux/issues/179
Just like below:
you will see warning with this code:
class Root extends Component {
render() {
return (
<Router history={browserHistory} createElement={this.createElement}>
<Route component={App}>
<Route path="/" component={MainPage}/>
<Route path="/page2" component={Page2}/>
<Route path="/settings" component={SettingsPage}/>
</Route>
</Router>
)
}
}
but you won't see warning with this code:
const routes = (
<Route component={App}>
<Route path="/" component={MainPage}/>
<Route path="/page2" component={Page2}/>
<Route path="/settings" component={SettingsPage}/>
</Route>
);
class Root extends Component {
render() {
return (
<Router history={browserHistory} createElement={this.createElement}>
{routes}
</Router>
)
}
}
This is OK, awesome solution to vanish [react-router] warning, and for Root Component changing state the routes was static and you won't see any warnings. BUT my issue is: I pass Root Component props to each Route and I can not do the above solution 😞 ,
I must put App Route inside Router so with this method absolutely this is not solution method and I will saw the known warning again, see my router code:
export default class AppRoutes extends Component {
render() {
return (
<Router history={hashHistory}>
<Route path="/" {...this.props} component={App}>
<IndexRoute component={Home} {...this.props}/>
<Route path="/transaction" component={Transaction} {...this.props}/>
<Route path="/users-management" component={UsersManagement} {...this.props}/>
<Route path="/issues" component={Issues} {...this.props}/>
<Route path='/not-found' component={NotFound}/>
<Route path='/settlement-management' component={SettlementManagement} {...this.props}/>
<Route path='/categories-management' component={CategoriesManagement} {...this.props}/>
<Route path='/gifts-management' component={GiftsManagement} {...this.props}/>
<Redirect from='/*' to='/not-found'/>
</Route>
</Router>
);
}
}
And the Root Component render code is:
render(){
return(
<AppRoutes {...this}/>
);
}
I passed this as a props to AppRoutes component and I need to pass inherited this.props to sub Routes and use them. how I could won't see warning and pass props to any Routes?
One of my solution is that, I write all Routes as static and call Root Component props directly inside each component, but how? I don't know how I can call and keep props of Root Component inside the component that need to have props of Root Component as the component is not direct Root Component children?
You can use render route prop instead of component to pass props to your components :
<Route path="/transaction" render={() => <Transaction {...this.props} />} />
Edit : Or this to also pass route props :
<Route path="/transaction" render={(routeProps) => <Transaction parentProps={this.props} {...routeProps} />} />
(I think it's better to pass individual custom parent props to not enter in conflict with routeProps)
Trying to use browserHistory.push method to change my route programmatically.
It will change the route (per browser address bar) but doesn't update the view.
Here's my code
App.jsx
const AppStart = React.createClass({
render: function() {
return (
<MuiThemeProvider>
<Router history={hashHistory}>
<Route path="/" component={Main}>
<Route path="experiences" component={Experiences} />
<Route path="people" component={Profiles} />
<Route path="login" component={Login} />
<IndexRoute component={Home}/>
</Route>
</Router>
</MuiThemeProvider>
);
}
});
ReactDOM.render(
<AppStart />,
document.getElementById('app')
);
Component:
handleLoginRedirect(e) {
browserHistory.push('/experiences');
},
render() {
return (
<div className='row'>
<div className='col-sm-10 col-sm-offset-1'>
<form role='form'>
<RaisedButton label="Redirect" onClick={this.handleLoginRedirect} />
</form>
</div>
</div>
);
Your router configuration uses hashHistory while you're pushing onto browserHistory.
It's easy to miss something like this and it's understandable.
Replace hashHistory with browserHistory in your Router like so:
<Router history={browserHistory}>
Full Snippet:
const AppStart = React.createClass({
render: function() {
return (
<MuiThemeProvider>
<Router history={browserHistory}>
<Route path="/" component={Main}>
<Route path="experiences" component={Experiences} />
<Route path="people" component={Profiles} />
<Route path="login" component={Login} />
<IndexRoute component={Home}/>
</Route>
</Router>
</MuiThemeProvider>
);
}
});
If you're using the newest react-router api you'll need to use:
this.props.history.push('/path/goes/here');
You may need to bind this to your function when accessing this.props (note: may):
onClick={this.handleLoginRedirect.bind(this)}
Please refer to the following question for all the information on this topic:
Programmatically navigate using react router