Reputation: 646
I'm new to React JS and am trying to implement something similar to the Angular sample application.
I have a table of customers and want to seen the selected customer at the bottom of the table.
I tried the following with react-router-dom:
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import 'bootstrap/dist/css/bootstrap.css';
ReactDOM.render((<BrowserRouter><App /></BrowserRouter>), document.getElementById('root'));
registerServiceWorker();
// App.js
import React, { Component } from 'react';
import { Route } from 'react-router-dom/Route';
import Customers from './components/customers';
import Customer from './components/customer';
export default class App extends Component {
state = {
};
render() {
return (
<React.Fragment>
<Customers />
<Route path={`/customer/:id`} component={Customer} />
</React.Fragment>
);
}
}
// customers.jsx
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
export default class Customers extends Component {
state = {
customers: []
};
render() {
return (
<React.Fragment>
<header className="jumbotron"><h1>Customer List</h1></header>
<div className="container">
<table className="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
</tr>
</thead>
<tbody>
{this.state.customers.map(c => (<tr key={c.id}><td><Link to={`/customer/${c.id}`}>{c.name}</Link></td><td>{c.address}</td></tr>))}
</tbody>
</table>
<hr />
</div>
<footer className="footer">© 2018</footer>
</React.Fragment>
);
}
async componentDidMount() {
const result = await fetch('http://api.com/customers');
const customers = await result.json();
this.setState({ customers });
console.log(this.state.customers);
}
}
// customer.jsx
import React, { Component } from 'react';
export default class Customer extends Component {
render() {
return (<p>Customer</p>);
};
}
The line in App.js that adds the Route (Route path={/customer/:id
} component={Customer}) is causing the error. If I remove that line I can see the table of customers but as soon as I add this line, then I get that error message.
Did I miss something on how this router works?
Thank you.
UPDATE
Event changing App.js to this very simple version causes the error
import React, { Component } from 'react';
import { Route } from 'react-router-dom/Route';
export default class App extends Component {
state = {
};
render() {
return (
<div>
<Route exact path='/' render={() => (<h1>Hello</h1>)} />
<Route exact path='/customer' render={() => (<h1>Customer</h1>)} />
</div>
);
}
}
The full error message is:
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, or you might have mixed up default and named imports.
Upvotes: 3
Views: 8669
Reputation: 11600
change this:
import {Route} from "react-router-dom/Route";
to this:
import Route from "react-router-dom/Route";
Route is a default export when you access it directly: "react-router-dom/Route"
You can use named exports when you import Route
from base package
import {Route} from "react-router-dom";
But don't mix the two.
Upvotes: 3
Reputation: 30360
Looks like you have a syntax error in the Customer
component's render()
method which will be causing issue when you attempt to use/render this.
Try the following fix:
export default class Customer extends Component {
render() {
return (<p> Customer</p>); // <-- remove the whitespace in
// closing tag </p> like so
};
}
Upvotes: -1
Reputation: 33974
I feel the issue is with back ticks in path. Can you try with this
render() {
return (
<React.Fragment>
<Customers />
<Route path='/customer/:id' component={Customer} />
</React.Fragment>
);
}
OR
render() {
return (
<React.Fragment>
<Customers />
<Route path={'/customer/:id'} component={Customer} />
</React.Fragment>
);
}
Upvotes: 0