I'm newbie in reactjs, I tried build something with it but I had problem with react-router-redux. I get React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. in console. Here is my code :
App.js
import React, { PropTypes } from 'react';
class App extends React.Component {
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
export default App;
Routes.js
import React from 'react';
import { Route, IndexRoute } from 'react-router'
import App from './components/App';
import Login from './components/login/Login';
import Register from './components/register/Register';
export default (
<Route path="/" component={App}>
<IndexRoute component={Login}/>
<Route path="register" component={Register}/>
</Route>
);
And Index.js
...
import { syncHistoryWithStore } from 'react-router-redux'
import { Router } from 'react-router'
import { createBrowserHistory } from 'history';
import routes from './routes';
const store = configureStore();
const history = syncHistoryWithStore(createBrowserHistory(), store)
ReactDOM.render(
<Provider store={store}>
<Router history={history} routes={routes}>
</Router>
</Provider>,
document.getElementById('app')
);
Where is my wrong? Please explain for me why I get this error. Thank in advance
React-router-redux is no longer maintained and support only 3.x and 2.x React-router versions
Repo authors suggest using connected-react-router for React-rotuer 4.x bindings
There are different routers for different environments, you want to use BrowserRouter instead of Router.
See React Training BrowserRouter for more information.
index.js
// change this line
import { Router } from 'react-router';
// to
import { BrowserRouter as Router } from 'react-router-dom';
NOTE: You might also have to pass in your routes in a different way. This is shown in the React Training page provided above.
Related
When I try to render the "Home" component it just doesn't show anything... The path is correct, and the Router imports should be fine too. What am I missing? It worked on another project of mine and even if I copy and paste that code it doesn't seem to work.
App.js:
import React from "react";
import Home from "./components/Home"
import {BrowserRouter as Router, Route, Routes} from "react-router-dom"
function App() {
return (
<Router>
<Routes>
<Route exact path="/" element={<Home/>}/>
</Routes>
</Router>
);
}
export default App;
Home.js:
import React from 'react'
function Home() {
return (
<div>Home</div>
)
}
export default Home
index.js:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
reportWebVitals();
I expected the "Home" component to be rendered as soon as I load the page, but it wasn't (Blank page). I checked if I imported it incorrectly, but as soon as I delete the "Router" and "Routes" tags as well as the Route itself and just try to render the "Home" component on its own, it works.
It's probably something really small that I'm missing but I can't seem to figure it out right now.
Using Route requires Switch component which means you'll do the following:
import React from "react";
import Home from "./components/Home"
import {BrowserRouter as Router, Route, Routes, Switch} from "react-router-dom"
function App() {
return (
<Switch>
<Route exact path="/" >
<Home/>
</Route>
</Switch>
);
}
export default App;
I have the following ReactJS project structure and I'm getting the following error:
./src/index.js
Attempted import error: './components' does not contain a default export (imported as 'App').
My goal is to import components like this: import { App, Navbar } from 'components'; (notice the 'components') and not like ./components/App, ./components/App/index or so. To do that, I needed to add index.js in the components directory. I tried doing that by the following code, but I'm receiving the error above.
What's the reason? How do I solve it?
There are similar threads, but I'm already exporting it by export default App; in ./components/App/index.jsx. Maybe the reason is the .jsx extension?
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();
components/index.js
export App from './App';
components/App/index.jsx
import React, { Fragment } from 'react';
import './style.css';
import { BrowserRouter as Router, Switch, Route, Redirect } from 'react-router-dom';
import NotAuthorizedRoute from '../../common/NotAuthorizedRoute';
import { Navbar, Home, User, Login } from 'components';
const App = () => {
return (
<Fragment>
<Router>
<Navbar />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/users" component={User} />
<NotAuthorizedRoute path="/sign-in" component={Login} />
<Redirect from="*" to="/" />
</Switch>
</Router>
</Fragment>
);
};
export default App;
components/App/style.css
What I tried:
I tried doing the following, like people said in this thread: Attempted import error: 'App' is not exported from './App'.
components/index.js
export { App } from './App'; // note the brackets
But then I got:
./src/components/index.js
Attempted import error: 'App' is not exported from './App'.
It seems you are having some confusions with ES6 export/import syntaxes. MDN documentation is very explicative, I would recommend you to check it.
The most important thing is to remember the difference between default and named export/import. (HINT: When you see brackets in export/import statements you are dealing with named ones)
In your specific case, you will have to do as follows:
./components/component-a.jsx
const ComponentA = () => {
return (
<MyComponent/>
);
};
export {ComponentA};
./components/component-b.jsx
const ComponentB = () => {
return (
<MyComponent/>
);
};
export {ComponentB};
./components/index.js
import {componentA} from './component-a.jsx';
import {componentB} from './component-b.jsx';
export {componentA, componentB};
./some-file.jsx
import {componentA, componentB} from './components';
./some-other-file.jsx
import {componentA} from './components';
This is the typical pattern to create a virtual export/import namespace for logical module classification.
Please note that I've not used default exports. There are several opinions about this, but I would recommend to not use them to avoid errors like the one you are having.
Please also note that you'll always have to specify the full relative path to the components directory. The only way to import things from 'components' is by having a components package installed in your node_modules directory.
Make sure you are not using the exported value componentA in {componentA}
remove `{}` and check
I am trying to set a basic example of react router where I have two simple routes, greetings and signup, under a template setup. Currently, I am not getting any errors on load, however, when trying to access the /signup route by typing it in to the address bar, I am getting the following error: Cannot GET /signup and I am having trouble understanding why.
Did anyone else run into this issue with react-router-dom v4? I appreciate any suggestions on how to resolve this issue and allow the successful navigation to different paths via URL.
Note, if I try to access these url paths using the built in react Link component and clicking on the link, its works as expected, but when refreshing the page at the url, I get the Cannot GET signup error again.
app.js
import React from "react";
import NavigationBar from '../components/navigation-bar';
export class App extends React.Component {
render() {
return (
<div className="container">
<NavigationBar />
{this.props.children}
</div>
);
}
}
index.js
import React from 'react';
import ReactDOM from "react-dom";
import {Provider} from "react-redux";
import {createStore} from "redux";
import allReducers from "./reducers";
import {BrowserRouter as Router, Route, Switch} from "react-router-dom";
import {App} from "./components/app";
import {Greetings} from "./components/greetings";
import {Signup} from "./components/signup";
const store = createStore(allReducers);
ReactDOM.render(
<Provider store={store}>
<Router>
<App>
<Switch>
<Route exact path="/" component={Greetings} />
<Route path="/signup" component={Signup} />
</Switch>
</App>
</Router>
</Provider>, window.document.getElementById("app"));
greetings.js
import React from "react";
export class Greetings extends React.Component {
render() {
return (
<h2>
Greetings
</h2>
);
}
}
signup.js
import React from "react";
export class Signup extends React.Component {
render() {
return (
<h2>
SIGN UP
</h2>
);
}
}
Try using HashRouter over BrowserRouter because to use BrowserRouter web server must be ready to handle real URLs.
import {HashRouter as Router, Route, Switch} from "react-router-dom";
React noob here, I'm trying to add a link in my material-ui toolbar using React-router v4 to the home page but I keep getting the 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 LandingToolBar.
I'm trying to copy the basic example here https://reacttraining.com/react-router/web/example/basic but instead putting the top list in another component called LandingToolBar but I can't see to get it to work. Here is my index.js:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import injectTapEventPlugin from 'react-tap-event-plugin'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
injectTapEventPlugin();
ReactDOM.render(
<MuiThemeProvider>
<App />
</MuiThemeProvider>,
document.getElementById('app')
);
My app.js:
import React from 'react'
import {Route, BrowserRouter, Switch} from 'react-router-dom'
import LoginPage from "./containers/LoginPage";
import SignUpPage from "./containers/SignUpPage";
import HomePage from "./components/landing/HomePage";
import LandingToolBar from "./components/landing/LandingToolBar";
class App extends React.Component {
render() {
return (
<BrowserRouter>
<div>
<LandingToolBar/>
<Switch>
<Route path="/" exact component={HomePage}/>
<Route path="/login" component={LoginPage}/>
<Route path="/signup" component={SignUpPage}/>
</Switch>
</div>
</BrowserRouter>
)
}
}
export default App;
And the toolbar component LandingToolBar that I'm trying to render always:
import React from 'react';
import Link from 'react-router-dom';
import {ToolbarGroup, ToolbarTitle, RaisedButton, Toolbar} from 'material-ui'
const LandingToolBar = () => (
<Toolbar>
<ToolbarGroup>
<ToolbarTitle text="ETFly"/>
<Link to="/">feafeaf</Link>
</ToolbarGroup>
</Toolbar>
);
export default LandingToolBar;
Struggling pretty hard with the routing part as there doesn't seem to be much explanation in the docs or for v4 stuff...
Thanks for the help!
You need to import the Link like this, its a named import not default import:
import {Link} from 'react-router-dom';
Check this answer for named vs default import/export.
I have this code. What I want to do is when I click a button 'feature' it will take me to index route. However, React keeps saying 'can not read property push of undefined' What I've done wrong?
route.js
import React from "react";
import ReactDOM from "react-dom";
import {Router, Route, hashHistory, IndexRoute } from "react-router";
import Layout from "./page/Layout";
import Features from "./page/Features";
import Features from "./page/archive";
const app = document.getElementById('app');
ReactDOM.render(
<Router history={hashHistory}>
<Route path="/" component={Layout}>
<IndexRoute component={Features} />
<Route path="archive" component={Archive} />
</Route>
</Router>, app);
Layout component
import React from "react";
import {Link, Router, Route, hashHistory} from "react-router";
export default class Layout extends React.Component{
navigate(){
this.context.router.push('/');
}
render(){
return(
<div>
{this.props.children}
<button onClick={this.navigate.bind(this)}>feature</button>
</div>
)
}
}
package.json - partial
"react": "^0.14.7",
"react-dom": "^0.14.7",
"react-router": "^2.0.1"
"history": "^2.0.1",
-------------update to jordan's answer-------------
In React Router v4, you no longer have to give a history to your router. Instead you just use BrowserRouter or HashRouter from 'react-router-dom'. But that makes it unclear how to push a rout to your history when you aren't in a react component.
The solution is to use the history package.
Just import createHistory like this:
import createHistory from 'history/createBrowserHistory'
Or the way I do it is like this:
import { createHashHistory } from 'history'
then create your history
export const history = createHashHistory()
and now you can push to it:
history.push('/page')
I hope this helps others who come to this question. None of the current answers gave me what I needed.
This may not be referring to above example but I had the same error. After lot of debugging I figured out that history is not reachable to my inner components. Make sure your history is reachable.
//main.js
<BrowserRouter>
<div>
<Route path="/" component={Home}/>
<Route path="/techMap" component={TechMap}/>
</div>
</BrowserRouter>
//app.js
<div>
<TechStack history= {this.props.history}/>
</div>
//techstack.js
<div>
<span onClick={this.search.bind(this)}>
</span>
</div>
)
search(e){
this.props.history.push('/some_url');
}
TechStack is my inner component.
Earlier I was able to get history in app.js but not in tech.js.
But after passing props in form of history, I got the history in tech.js and routing works
With React router v4, you need to wrap the components in withRouter. Then you can access history in your components. Do the following:
import { withRouter } from 'react-router-dom';
...
...
export default withRouter(MyComponent);
You need to change your route.js page to
import {Router, browserHistory} from 'react-router';
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" component={Layout}>
<IndexRoute component={Features} />
<Route path="archive" component={Archive} />
</Route>
</Router>, app);
And then everywhere you want to navigate you can use
import {Router, browserHistory} from 'react-router';
browserHistory.push('/');
The react-router docs encourage you to use browserHistory instead of hashHistory
hashHistory uses URL hashes, along with a query key to keep track of
state. hashHistory requires no additional server configuration, but is
generally less preferred than browserHistory.
usually, when you are trying to redirect from a nested component it will give this error.
there are a few ways to fix it
Using react-dom you can import the withRouter component from react-router-dom then use it as usual with this.props.history.push and instead of the usual export default 'class' we will use export default withRouter(class); and boom problem solve.
I use browserHistory instead of HashHistory.
Then I just need to do the following:
import { browserHistory } from 'react-router'
// ...
// ...
navigate(){
browserHistory.push('/');
}
You don't need to use browserHistory anymore.
React-router-dom inject into your component route related props and context.
One of this props is 'history' and on this history object is a function push that you can call and pass the route you want to navigate to.
example in a Class base component, you can create a function like below as an onClick handler to redirect to specific link
redirectToPage() {
this.props.history.push('/page'); OR
this.context.router.history.push('/page');
}
while in a function base stateless component
redirectToSessionStatePage() {
props.history.push('/page');OR
context.router.history.push('/page');
}
Change your Layout component to have navigate assigned to ES6 lambda. This is needed to set the correct value of this
import React from "react";
import {Link, Router, Route, hashHistory} from "react-router";
export default class Layout extends React.Component{
navigate = () => {
this.context.router.push('/');
}
render(){
return(
<div>
{this.props.children}
<button onClick={this.navigate.bind(this)}>feature</button>
</div>
)
}
}
export default class Layout extends React.Component{
navigate = () => {
this.context.router.push('/');
}
render(){
return(
<div>
{this.props.children}
<button onClick={this.navigate.bind(this)}>feature</button>
</div>
)
}
}
Layout.contextTypes = {
router: PropTypes.object.isRequired
}
It looks like you overwrote your Features import with whatever is in your /archives directory. In the code you posted, you have this:
import Features from "./page/Features";
import Features from "./page/archive";
import {withRouter} from 'react-router-dom';
export default withRouter(AppName);