I'm running react-router-dom 4.1.1, I followed multiple React Router guides, even doing the react-router-tutorial which worked on my computer (though it was using react-router v2 or something similar). When I attempt to use react-router-dom v4 on a simple application, I run into many errors.
Scroll Down for Current Code & Error
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import createBrowserHistory from 'history/createBrowserHistory'
import App from './components/App';
import About from './components/pages/about';
const customHistory = createBrowserHistory()
ReactDOM.render((
<Router history={customHistory}>
<Switch>
<Route path='/' component={App} />
<Route path='/about' component={About}/>
</Switch>
</Router>
), document.getElementById('root'))
This code alone works and renders my 'App' component
But when I try to add a 'Link' component in my App component, it won't recognize it.
//App.js
import React from 'react';
import Header from './Header';
import { Link } from 'react-router-dom'
class App extends React.Component {
render() {
return (
<div className="App">
<Header className="Header" header="Header" />
<main className='main'>
<Link to='about'>About</Link>
</main>
</div>
);
}
}
export default App;
If I run this, I get the error:
TypeError: Cannot read property 'history' of undefined
at Link.render (/Users/Ryan/Desktop/df/grnd/node_modules/react-router-dom/Link.js:76:35)
at /Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:795:21
at measureLifeCyclePerf (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:75:12)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext
(/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:794:25)
at ReactCompositeComponentWrapper._renderValidatedComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:821:32)
at ReactCompositeComponentWrapper.performInitialMount (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:361:30)
at ReactCompositeComponentWrapper.mountComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:257:21)
at Object.mountComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactReconciler.js:45:35)
at ReactDOMComponent.mountChildren (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactMultiChild.js:236:44)
at ReactDOMComponent._createContentMarkup (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactDOMComponent.js:659:32)
If I comment out the 'Link' component in App.js, the program runs and loads 'App' from index.js.
This is only one error I've received out of many as I try to figure out why I can't run it. I have also received errors in which it says 'Route' is undefined or that 'Router' can't have nested children and so on. I find this problem to be at it's simplest.
The history I used for this example was taken from the example given on:
https://reacttraining.com/react-router/web/api/Router/history-object
First of all, you use a BrowserRouter, this one creates its own history object and uses this one. Therefore in your case you shouldn't be passing a history object to it. Actually it should even print a warning in your console after I looked at the code of BrowserRouter. And if I were you I'd keep it named as BrowserRouter, it makes it less error prone and clearer when you read the code.
Then, in v4, the Router can only have 1 child. But in the case of the Switch, it actually mounts only the matching route. I'm not sure if it's intended to be like this, try to change your hierchy to something different, and have the child of Router to always be mounted. Here would be an example taking your code :
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import App from './components/App';
ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>
), document.getElementById('root'));
And then in your App you build your routing logic, that even makes more sense, since your App is probably the application, therefore it should always be present.
//App.js
import React from 'react';
import Header from './Header';
class App extends React.Component {
render() {
return (
<div className="App">
<Header className="Header" header="Header" />
<Switch>
<Route exact path='/' component={Home} />
<Route path='/about' component={About}/>
</Switch>
</div>
);
}
}
And your links would probably be inside the Header I suppose, or you may want to build a special Nav component for this, that may be included in the Header or some place else. Let's do it in the Header for now and see how that would work:
//Header.js
import React from 'react';
import {Link} from 'react-router-dom';
class Header extends React.Component {
render() {
return (
<header className="header">
<Link to='/'>Home</Link>
<Link to='/about'>About</Link>
</header >
);
}
}
Current Code
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './components/App';
ReactDOM.render((
<BrowserRouter>
<App/>
</BrowserRouter>
), document.getElementById('root'))
//App.js
import React from 'react';
import Header from './Header';
import Main from './Main';
class App extends React.Component {
render() {
return (
<div className="App">
<Header className="Header" header="Header" />
<Main className="Main" />
</div>
);
}
}
export default App;
//Main.js
import React from 'react';
import { Switch, Route } from 'react-router-dom'
import Home from './Home';
import About from './About';
class Main extends React.Component {
render() {
return (
<div className='Main-Container'>
<Switch>
<Route exact path='/' component={Home} />
<Route path='/about' component={About} />
</Switch>
</div>
)
}
}
export default Main;
Most Recent Error
Warning: Failed context type: The context router is marked as
required in Switch, but its value is undefined.
in Switch (created by Main)
in div (created by Main)
in Main (created by App)
in div (created by App)
in App TypeError: Cannot read property 'route' of undefined
at Switch.render (/Users/Ryan/Desktop/df/grnd/node_modules/react-router/Switch.js:48:36)
at /Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:795:21
at measureLifeCyclePerf (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:75:12)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext
(/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:794:25)
at ReactCompositeComponentWrapper._renderValidatedComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:821:32)
at ReactCompositeComponentWrapper.performInitialMount (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:361:30)
at ReactCompositeComponentWrapper.mountComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:257:21)
at Object.mountComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactReconciler.js:45:35)
at ReactDOMComponent.mountChildren (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactMultiChild.js:236:44)
at ReactDOMComponent._createContentMarkup (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactDOMComponent.js:659:32)
I found out what's causing the error: Server Rendering
Currently, I am using this piece of code
//server.js
server.get('/', (req, res) => {
res.render('index', {
content: ReactDOMServer.renderToString(<App />)
});
});
Which renders to my ejs template
//index.ejs
<%- include('header') -%>
<div id="root"><%- content -%></div>
<%- include('footer') -%>
When I comment out content: ReactDOMServer.renderToString(<App />)and switch it to something like content: 'Hello' .... <Route/> and <Link/> work.
Related
index.js page:
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import NewUpload from './components/newUpload';
import Testing from './components/Testing';
import Landing from './landing/Landing';
import * as serviceWorker from './serviceWorker';
ReactDOM.render( <Router>
<Route path='/upload' component={NewUpload} />
<Route path='/' component={Testing} />
<Route path='/landing' component={NewUpload} />
</Router>, document.getElementById('root'));
Testing.js (this is the first page that loads upon npm start):
import React, { Component } from 'react';
export default class Testing extends Component{
render()
{
return ( <div>
<form action='/upload'>
<button type="button">click to upload</button>
</form>
</div>
)
}
}
So when I click on this button, it sure routes me to the new page, but the button is still visible on the new page as well. How do I get rid of this?
Add the exact prop to the Route component.
<Route exact path='/' component={Testing} />
This ensure that the path matches the location.pathname exactly.
See the docs here
I have the following index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import Main from './main/main';
import './index.css';
ReactDOM.render(
<BrowserRouter><Main /></BrowserRouter>,document.getElementById('root'));
the following in main.js:
import React, { Component } from 'react';
import NavMenu from "./navmenu";
import Content from "./content";
import './main.css';
class Main extends Component {
render() {
return (
<div id="main-layout">
<div id="main-header">
<div><img src={(require("./images/ppslogo-small.png"))} alt="eeeee"/></div>
<div><h2>Lil Test By Me</h2></div>
</div>
<div id="main-content">
<NavMenu />
<Content />
</div>
<div id="main-footer">
<div>Copyright © 2020. Powered By me. All Rights Reserved.</div>
</div>
</div>
);
}
}
export default Main;
And The following in content.js
import React, { Component } from 'react';
import {Route, Switch} from 'react-dom';
import Dashboard from "../dashboard/dashboard";
import Invoicing from "../invoicing/invoicing";
class Content extends Component {
render() {
return(
<Switch>
<Route exact path="/Dashboard" component={Dashboard} />
<Route path="/Invoicing" component={Invoicing} />
</Switch>
)
}
};
export default Content
It it my attempt to create an SPA with the Content component as my target for all my subsequent pages; however, I am clearly doing something wrong as I am getting all kinds of errors all over the place. Can anyone immediately see what I am doing incorrectly here?
Route and Switch needs to be imported from react-router-dom instead of react-dom
import React, { Component } from 'react';
import {Route, Switch} from 'react-router-dom';
import Dashboard from "../dashboard/dashboard";
import Invoicing from "../invoicing/invoicing";
class Content extends Component {
render() {
return(
<Switch>
<Route exact path="/Dashboard" component={Dashboard} />
<Route path="/Invoicing" component={Invoicing} />
</Switch>
)
}
};
export default Content
Use react-router-dom instead of react-router and then
change your content.js code to this.
import React, { Component } from 'react';
import {Route, Switch, BrowserRouter as Router} from 'react-router-dom';
import Dashboard from "../dashboard/dashboard";
import Invoicing from "../invoicing/invoicing";
class Content extends Component {
render() {
return(
<Router>
<Switch>
<Route exact path="/dashboard" component={Dashboard} />
<Route path="/invoicing" component={Invoicing} />
</Switch>
</Router>
)
}
};
export default Content
notice that I have added Router above the switch. and changed react-router to react-router-dom and also transformed the routes to lowercase
i recently tried to make separate files .jsx in React. I made couple of them with export default name / import name from ./name.jsx'. But there comes problem. First i had imported Route and Links from react-router and console said it can't find Links, i found on stackoverflow to change it to react-router-dom, so i did it, and now console says i forgot to export some components. I can't find solution :( Could anyone help me ?
Here's my project :
https://github.com/tafarian/Portfolio
import React from 'react';
import ReactDOM from 'react-dom';
import './../css/style.scss';
import {
Router,
Route,
Link,
IndexLink,
IndexRoute,
hashHistory
} from 'react-router-dom';
import Template from './Template.jsx'
import Projects from './Projects.jsx'
import Home from './Home.jsx'
import AboutMe from './AboutMe.jsx'
import Contact from './Contact.jsx'
Such error as
"Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of App.
means that you are trying to create an undefined component, and as it said in error - usually this happens when you forget to export component or the component that you are importing does not exist.
When there is a lot of components and it's hard to find which one is "bad" I place a breakpoint at console.error(message); in React code and go up the stacktrace to the function createElement and it's arguments. Usually it helps me to identify the problem.
The main problem, is that your code is not compatible with react-router#4.
In this version you can not pass children and component to Route at the same time.
Also, there is no such a thing as IndexRoute and you should use BrowserRouter instead of Router, or you should pass an history object.
Take a look at the documention: https://reacttraining.com/react-router/web/guides/philosophy
And here is fixed version of yout app.jsx:
import React from 'react';
import ReactDOM from 'react-dom';
import './../css/style.scss';
import {
BrowserRouter,
Route,
Link,
hashHistory
} from 'react-router-dom';
import Template from './Template.jsx'
import Projects from './Projects.jsx'
import Home from './Home.jsx'
import AboutMe from './AboutMe.jsx'
import Contact from './Contact.jsx'
document.addEventListener('DOMContentLoaded', function(){
class App extends React.Component {
state = {
loading: true,
};
componentDidMount() {
setTimeout(() =>
this.setState({
loading: false
}), 2500);
}
render() {
if(this.state.loading === true) {
return (
<div id="preloader">
<div id="loader"></div>
</div>
)
}
return(
<BrowserRouter history={hashHistory}>
<Template>
<Route exact path="/" component={Home} />
<Route path='/aboutme' component={AboutMe} />
<Route path='/projects' component={Projects} />
<Route path='/contact' component={Contact} />
</Template>
</BrowserRouter>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('app')
);
});
While rewriting some components in es6 syntax my React router started throwing the following error:
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of `Navicon`.
This error only springs if I include a <Link> component inside my Navicon component, which looks like this:
import React from 'react';
import Link from 'react-router';
import './navicon.css';
class Navicon extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div className='navicon-container' tabIndex='0'>
<div className={'dropdown'}>
<Link to={'/'}>Hello</Link>
</div>
</div>
)
}
}
export default Navicon;
The component that mounts my router looks like this:
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, browserHistory, IndexRoute } from 'react-router';
import App from './components/App';
import Home from './components/Home';
import About from './components/About';
import './main.css';
ReactDOM.render(
<Router history={browserHistory}>
<Route component={App}>
<Route path='/' component={Home} />
<Route path='/about' component={About} />
</Route>
</Router>,
document.getElementById('app')
);
I'm using "react-router": "^3.0.2"
Does anyone have any idea what might be tripping this error? This error never sprang when I was using React.createClass(), so I'm puzzled.
Ah, it seems that due to the export syntax on react router components, one evidently must use:
// import Link from react-router <- this doesn't work
import {Link} from react-router // <- this does
That little change resolves the error.
I'm missing something extremely basic on this. - I've tried to implement react-router. I'm getting an error on page load:
Warning: Failed prop type: Invalid prop 'children' supplied to 'Router'.
in Router
Also, the configured routes don't seem to be being picked up correctly
e.g. Warning: [react-router] Location "/policies" did not match any routes
I've had a look around SO but nothing seems to be relevant to what I have.
What am I doing wrong?
index.js
import 'core-js/fn/object/assign';
import React from 'react';
import ReactDOM from 'react-dom';
import {Router, Route, IndexRoute, hashHistory, browserHistory } from 'react-router';
import {Dashboard} from './components/Main';
import {OverviewComponent} from './components/dashboard/OverviewComponent';
import {PoliciesComponent} from './components/dashboard/PoliciesComponent';
import {ReportingComponent} from './components/dashboard/ReportingComponent';
// Render the main component into the dom
//ReactDOM.render(<App />, document.getElementById('app'));
ReactDOM.render((
<Router history={browserHistory}>
<Route path="/" component={Dashboard}>
<Route path="/policies" component={PoliciesComponent} />
<Route path="/reports" component={ReportingComponent} />
</Route>
</Router>),
document.getElementById('app'));
excerpt from Main.js
import React from 'react';
import { Link } from 'react-router';
import {OverviewComponent} from './dashboard/OverviewComponent';
import {PoliciesComponent} from './dashboard/PoliciesComponent';
import {ReportingComponent} from './dashboard/ReportingComponent';
class Dashboard extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div id="mainContainer" className="container-fluid">
<div id="menuSidebar" className="col-md-2">
<MenuItems />
</div>
<div className="topNav"></div>
<div className="mainPanel">{this.props.children}</div>
</div>
);
}
}
export default Dashboard;