Fernando
Fernando

Reputation: 646

React JS - Route - Element type is invalid

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">&copy; 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

Answers (3)

marzelin
marzelin

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

Dacre Denny
Dacre Denny

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

Hemadri Dasari
Hemadri Dasari

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

Related Questions