Router history with react-router 4.0.0 - javascript

In react-router 4.0.0 the history provisoning seems to have changed, with the following index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, hashHistory } from 'react-router';
import App from './components/App';
import './index.css';
ReactDOM.render(
<Router history={hashHistory}>
<Route path="/" component={App} />
</Router>, document.getElementById('root')
);
I get:
Warning: Failed prop type: The prop `history` is marked as required in `Router`, but its value is `undefined`.
and an error afterwards. I browsed the code but can't find any example or API how that has changed.

React Router v4 changed things little bit. They made separate top level router elements. Replace <Router history={hashHistory}> with <HashRouter> in your code.
Hope this will help full.
import {HashRouter,Route} from 'react-router-dom';
<HashRouter>
<Route path = "/getapp" component = {MainApp} />
</HashRouter>

hashHistory is no longer an exported object of react-router. If you want to use a hash history, you can just render a <HashRouter>.
import { HashRouter } from 'react-router-dom'
ReactDOM.render((
<HashRouter>
<App />
</HashRouter>
), holder)

This is a topic where RR documentation should add more clarity... To answer your question, you can either use a BrowserRouter, or you can use a Router and pass it a history instance.
Go with the first approach when all your route changes are through Link components.
However, when you need to change routes from your store methods, you would need to use the latter approach. You can write a module which creates and exports a history object and then use the same object in your Router component and in the store methods. It's important to use the same object otherwise the Router won't be able to correctly sync the URL changes with your store.

You may try the code below:
import { Router } from 'react-router'
import createBrowserHistory from 'history/createBrowserHistory'
const history = createBrowserHistory()
<Router history={history}>
<App/>
</Router>
Check the doc here.

Related

Error: <Route> elements are for router configuration only and should not be rendered in react-router v4

Tried to upgrade react-router from 2 to 4 and broke it and now cant render my app.
getting various errors (the most recent is: <Route> elements are for router configuration only and should not be rendered)
I have also had the error where my ./ route renders fine but every other route blows up when I refresh and says Cannot GET /randomRoute
I am creating a react app and my main index.js file (where I include ReactDOM.render) also includes the routes and looks like so:
import React from 'react';
import ReactDOM from 'react-dom';
import { Route } from 'react-router';
import { BrowserRouter as Router, Match, HashRouter } from 'react-router-dom'
import Header from './components/header';
import './index.scss';
class App extends React.Component {
render() {
return (
<Router history={HashRouter}>
<div>
<Route path={"/"} component={Header} />
</div>
</Router>
);
}
}
ReactDOM.render(<App />,
document.getElementById('content'));
why would I be getting that current error and can anyone give me a simple start to the basics I need to include just to get routing working? it worked in version 2 but I wanted to upgrade and now cant get it working again
The problem is that you are specifying history object as a Router type.
From the Documentation
A <Router> that uses the hash portion of the URL (i.e.
window.location.hash) to keep your UI in sync with the URL.
This is similar to what you would do when you specify history as
hashHistory in Router v2.
Also, history object has been seprated into a seprate package from v4 onwards.
You can either make use of BrowserRouter or HashRouter to render your Routes.
Change your Route Configuration to below if you want to use BrowserRouter which is <Router> that uses the HTML5 history API (pushState, replaceState and the popstate event) to keep your UI in sync with the URL.This is similar to what you would do when you specify history as browserHistory in Router v2.
Also you need to import Route from 'react-router-dom'.
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Match, Route} from 'react-router-dom'
import Header from './components/header';
import './index.scss';
class App extends React.Component {
render() {
return (
<Router >
<div>
<Route path={"/"} component={Header} />
</div>
</Router>
);
}
}
Well, in react router v4 the API is different. You have to define it in your index.js file like this,
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<div>
<Switch>
<Route path="/path/one" component={ComponentOne} />
<Route path="/path/two" component={ComponentTwo} />
<Route path="/" component={IndexComponent} />
</Switch>
</div>
</BrowserRouter>
</Provider>
, document.querySelector('.container'));
Make sure the order is important here. Put the most generic one at last. Hope this helps. Happy coding !

React router basic implementation

I am trying to implement React router and I have a class called App from which I want to call ExpenseApp. For ExpenseApp to work, it requires 'data' which I want to pass. Also, my first page of get loaded should be ExpenseApp. As far as I understood react-router, the class name to be specified in the '/' path is the first page to be loaded. The question is how can I pass data from react router to the component.
import React from 'react'
import ReactDOM from 'react-dom'
import {ExpenseApp} from './expense-app.js'
import {Switch, BrowserRouter, Route} from 'react-router-dom'
import {FullBlog} from './FullBlog.js'
var data=[
{
"Author":"Dan Brown",
"Book":"Inferno"
},
{
"Author":"Jeffrey Archer",
"Book":"Be careful what you wish for"
},
{
"Author":"Paulo Coelho",
"Book":"The Alchemist"
}
];
class App extends React.Component{
render(){
return(
<Router>
<Route path='/' component={ExpenseApp}/>
<Route path='fullblog' component={FullBlog}/>
</Router>
)
}
}
ReactDOM.render(<App/>, document.getElementById('container'))
And normally when I was displaying the component without using the react-router, I was doing something like
I am still confused with the concepts of react-router, how can I implement this?
maybe you can try this one :
<Router>
<Route exact path='/' render={() => <ExpenseApp data={data} />}/>
<Route path='fullblog' component={FullBlog}/>
</Router>
this is using react router v4, hope can solve your issue :)
As far as I know, you usually would want to fetch data from within the component, but if it is not possible or you do not want to do this, you could try using decorateComponentWithProps (https://github.com/belle-ui/decorateComponentWithProps)
import decorateComponentWithProps from 'decorate-component-with-props';
// ...
<Route path='/' component={decorateComponentWithProps(ExpenseApp, {data})} />
Given that the ExpenseApp's prop name is data
Edit: As found out in the comments, you also need to change
import {Switch, BrowserRouter, Route} from 'react-router-dom'
to
import {Switch, BrowserRouter as Router, Route} from 'react-router-dom'
For the code to work, or you can also change the usage of <Router /> to <BrowserRouter />

Pagination issue using React Router v4.1

I'm migrating a site in ASP.NET MVC to REACT. And for pagination i have created a component in React.
Issue i'm facing is with Routing for the pagination URLs. React Router is not able to detect that the URL is different when i click on a pagination URL
Let me explain:
app.js code:
import React from 'react';
import ReactDOM from 'react-dom';
import {createStore, applyMiddleware} from 'redux';
import allReducers from '../reducers/index';
import {Provider} from 'react-redux';
import ReduxPromiseMiddleware from 'redux-promise';
import { BrowserRouter, Route } from 'react-router-dom';
import Main from './main';
import Layout from './layout';
const app = document.getElementById('root');
const store = createStore(allReducers, applyMiddleware(ReduxPromiseMiddleware));
ReactDOM.render(<Provider store={store}>
<BrowserRouter>
<Layout>
<Main/>
</Layout>
</BrowserRouter>
</Provider>
,app);
Main component render:
render(){
return(
<main>
<Switch>
<Route exact path='/' component={HomePage}/>
<Route path='/posts' component={PostsRouter} />
<Route path='/studies' component={StudiesPage} />
</Switch>
</main>
);
}
PostsRouter component:
const PostsRouter = () => (
<Switch>
<Route exact path='/posts' component={PostsPage} />
<Route path='/posts/:page' component={PostsPage} />
</Switch>
);
For both /posts and /posts/2 i need the component to be PostsPage.
Lets say i'm at /home. Now i click a posts link and URL changes to /posts. Now if i click /posts/2 link, nothing happens. React Router doesn't detect that the URL is different.
And a weird thing i noted is that if i change the component:
<Route path='/posts/:page' component={PostsPage} />
to
<Route path='/posts/:page' component={StudiesPage} />
then React Router routes me to StudiesPage component if i click on /posts/2 link when i'm on /posts URL.
May be i'm missing something obvious. But i haven't been able to figure out a way after lots of attempts.
I suspect Sergey's comment was right, that's what my problem ended up being. I was fetching data within componentDidMount() but didn't realise that in order to actually update it with new data when the next page link was clicked, I needed to do the same thing inside componentWillReceiveProps(). You can see my full source here but the biggest key part was this:
componentWillReceiveProps(nextProps) {
this.setState({
loaded: false
});
this.fetchMediaItems(nextProps.match.params.page);
}
componentDidMount() {
this.fetchMediaItems(this.props.match.params.page);
}
componentWillReceiveProps() receives the new properties, including page number, when you click on the link to page 2, so you need to do whatever inside there to update with the new state.

What is meant to be passed in for the React Router <Router> history prop?

I'm using react router (version 4.0.0) and the Router component has a required prop named "history".
I know in previous versions of react-router you could import browserHistory or hashHistory from the package and pass that along as the history prop to <Router> but in v4 neither of those are available.
The documentation available for the project makes no mention of what do to about this required history prop here and here it references the hashHistory export that is no longer available in v4 of the package.
Any thoughts?
If you want to use component with history you should import
browserHistory or hashHistory from 'react-router
import { Router,browserHistory } from 'react-router';
<Router history={browserHistory} routes={...} />
or
import { Router,hashHistory } from 'react-router';
<Router history={hashHistory} routes={...} />
https://github.com/ReactTraining/react-router/tree/v3/docs
I was importing { Router } from 'react-router-dom' which does in fact have a required prop history but I needed to be importing { BrowserRouter as Router } from 'react-router-dom' which does not have a required prop history. That cleared up the issue for me.

React router not working

I have a simple react-router setup. Please see my code here -
https://github.com/rocky-jaiswal/lehrer-node/tree/master/frontend
It is the most basic setup for react-router, however in the browser I cannot get it working -
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route } from 'react-router';
import IndexContainer from './components/index-container';
import AboutContainer from './components/about-container';
import PagesContainer from './components/pages-container';
(function main() {
ReactDOM.render((
<Router>
<Route path="/" component={IndexContainer}>
<Route path="about" component={AboutContainer} />
<Route path="pages" component={PagesContainer} />
</Route>
</Router>),
document.getElementById('app')
);
})();
The trouble also is there is no error reported on the console. Even I change the URL the IndexComponent is always mounted. Also if I type http://localhost:3333/#/about it changes to http://localhost:3333/#/about?_k=bac2pt somehow and stays on the IndexComponent.
Could there be something wrong with my simple webpack config or versions of react / react-router?
Thanks,
Rocky
IndexContainer is your parent component, try adding { this.props.children } in your render() so AboutContainer and PagesContainer will show.

Categories

Resources