0

I have a parent Component as app.js

import React, { Component } from 'react'
import { Route, Link, BrowserRouter, HashRouter} from 'react-router-dom'
//import BrowserHistory from 'react-router/lib/BrowserHistory'
import {Scholarships} from './scholarships'

class App extends Component {
        render() {
                return (
                        <div>
                        <HashRouter>
                            <div>
                                <Route exact path='/' component={Home} />
                                <Route path='/hello' component={Hello} />
                                <Route path='/scholarship' component={Scholarships} />

                            </div>
                        <Scholarships /> 
                        </HashRouter>
                        </div>

                )

        }
}

const Home = () => <h1> Hello from home! </h1>
const Hello = () => <h2> Hello React </h2>

export default App

and there is a child component as scholarships.js

import React, {Component} from 'react'
import Request from 'react-http-request' //`https://www.npmjs.com/package/react-http-request`

class Scholarships extends Component {
        constructor(props) {
                super(props);
        }
        render() {
                return (
                        <Request
                                url = 'https://api.github.com/users/mbasso'
                                method = 'get'
                                accept = 'application/json'
                                verbose = {true}
                        >
                                {
                                        ({error, result, loading}) => {
                                                        if(loading) {
                                                                return <div id="scholarships"> loading... </div>;
                                                        }
                                                        else {
                                                                return <div id="scholarships"> { JSON.stringify(result) }</div> ;
                                                        }

                                                }
                                }
                        </Request>
                )
        }
}

export default Scholarships

It is throwing an error 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. bundle.js:357:9 and Error: A may have only one child element I'm just starting with react so it might be a noob question but I am struck up here, If I pass <Scholarships /> directly into main.js it is working as expected why I am not able to nest it here

Additionally I've also tried

  • const scholarship = () => <Scholarships />
  • const scholarship = <Scholarships />
  • const scholarship = () => (<Scholarships />)
  • const scholarship = () => {Scholarships}

I would also like to know that my Scholarship component is return plain JSON.Stringify text so why is it still a Object in reference of the error given by const scholarship = () => <Scholarship />

My main.js file

import React from 'react'
import ReactDOM from 'react-dom'
import App from './app'
import Scholarships from './scholarships'
ReactDOM.render(<App />, document.getElementById('root'))
Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142

1 Answers1

-1

Write it like this:

<HashRouter>
    <div>
        <Route exact path='/' component={Home} />
        <Route path='/hello' component={Hello} />
        <Route path='/scholarship' component={Scholarship} />
    </div>
    <Scholarships />
</HashRouter>

Reason: A React component can't return multiple React elements, but a single JSX expression can have multiple children, so if you want a component to render multiple things you can wrap them in a div.

Don't forget that the render() function is exactly a function. Functions always take in a number of parameters and always return exactly one value.

Update:

Render the routes like this, it will work:

ReactDOM.render(
    <HashRouter>
        <div>
            <Route exact path='/' component={Home} />
            <Route path='/hello' component={Hello} />
            <Route path='/scholarship' component={Scholarships} />

        </div>
        <Scholarships /> 
    </HashRouter>,
    document.getElementbyId('root')
)
Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
  • check the updated answer for reason. – Mayank Shukla Apr 05 '17 at 11:25
  • `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`. bundle.js:357:9` `Error: A may have only one child element` Throws this after the change – Harshit Chaudhary Apr 05 '17 at 11:39
  • r u rendering `App` in `ReactDOM.render(...)` ?? – Mayank Shukla Apr 05 '17 at 11:42
  • Check the updated question, pasted the **main.js** as well – Harshit Chaudhary Apr 05 '17 at 11:44
  • check the updated answer, render the routes directly inside ReactDOM.render, it will work. Reason i don't know i searched alot but didn't find the reason of this. I tried many ways but this is the only way it was working :) i voted to reopen ur question may be someone provide the reason of that. – Mayank Shukla Apr 05 '17 at 11:50
  • Its good to test it, But I am looking to convert the entire frontend into react and going with this approach will make a hell lot of mess in the main.js and management of that. – Harshit Chaudhary Apr 05 '17 at 11:53