React router not working - javascript

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.

Related

Migrate 'react-router' into 'react-router-dom' (v4)

I am learning React Routing and I am watching this tutorial:
https://www.youtube.com/watch?v=1iAG6h9ff5s
Its 2016 tutorial so I suppose something changed because 'react-router' not working anymore and I am supposed to use 'react-router-dom'.
I found that I must uninstall 'history' and 'react-router' and use 'react-router-dom' instead, but It not working as expected when I change it.
How to edit this to make it working with 'react-router-dom'?
import React from "react";
import ReactDOM from "react-dom";
import {Router, Route, IndexRoute, hashHistory} from "react-router";
import Layout from "./pages/Layout";
import Archives from "./pages/Archives";
import Featured from "./pages/Featured";
import Settings from "./pages/Settings";
const app = document.getElementById('app');
ReactDOM.render(
<Router history={hashHistory}>
<Route path="/" component={Layout}>
<IndexRoute component={Featured}></IndexRoute>
<Route path="archives" component={Archives}></Route>
<Route path="settings" component={Settings}></Route>
</Route>
</Router>,
app);
My edit:
import React from "react";
import ReactDOM from "react-dom";
import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom";
import Layout from "./pages/Layout";
import Archives from "./pages/Archives";
import Featured from "./pages/Featured";
import Settings from "./pages/Settings";
const app = document.getElementById('app');
ReactDOM.render(
<Router>
<Route path="/" component={Layout}>
<Route path="/featured" component={Featured}/>
<Route path="/archives" component={Archives}/>
<Route path="/settings" component={Settings}/>
</Route>
</Router>,
app);
Also pushState not working...
Layout.js
import React from "react";
import {Link} from "react-router-dom";
export default class Layout extends React.Component {
navigate() {
this.props.history.pushState(null, "/");
}
render() {
return (
<div>
{this.props.children}
<h1>Welcome</h1>
<button onClick={this.navigate.bind(this)}>Featured</button>
</div>
);
}
}
When I click to Link url change, but content is not loaded... Also when I access url I get "Cannot GET" error
After watching the video, you probably want something like this. At first this would not be so easy to understand but after seeing a few of them you digest it. First you render your Layout with one Route. Then in this top route, you use other Routes to setup your components.
We usually use exact props for a top root like /. If you don't setup your app like that, for example all your routes is in your top Router config, then to use a route something like /featured we must have exact prop. If we don't use it Router always hit / path and we always see the top level component.
But, in your situation, you want other components to be routed in your top level component. So, we drop exact prop here.
Also you can use push to change history.
Update
After think about the navigation button named "Featured", I think you want the Featured component rendered as default one here. When hit the button again you will come back to Featured one. I've changed the code according to that. In this version, we add a / route in the Layout and point it to Featured. So, when we come here it is rendered. But, we use exact prop here since we also want routes like "/featured", "/archives" and "/settings".
export default class Layout extends React.Component {
navigate = () => this.props.history.push("/");
render() {
return (
<div>
<h1>Welcome</h1>
<Link to="/featured">Featured</Link>
<Link to="/archives">Archives</Link>
<Link to="/settings">Settings</Link>
<br />
<button onClick={this.navigate}>Featured</button>
<Route exact path="/" component={Featured} />
<Route path="/featured" component={Featured} />
<Route path="/archives" component={Archives} />
<Route path="/settings" component={Settings} />
<div>
Some other info.
</div>
</div>
);
}
}
const app = document.getElementById('root');
ReactDOM.render(
<Router>
<Switch>
<Route path="/" component={Layout} />
</Switch>
</Router>,
app);

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.

Router history with react-router 4.0.0

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.

Categories

Resources