1
votes

Disclaimer: I've seen react-router is not rendering anything and You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports but the solutions in there did not work for my case.

I am trying to render two component in a Switch in App.js like this

     render() {

      let MyHome = (props) => {
          return(
              <Home {...props} toggleFilter={this.state.filterDrawerOpen}/>
          )
      }
        console.log("Mue")
      let backdrop;
      if (this.state.sideDrawerOpen) {
          backdrop = <Backdrop click={this.backdropClickHandler} />
      }

    return (
        <div className="container-fluid">

                <div className="row">
                <Toolbar
                        filterClickHandler = {this.filterToggleClickHandler}
                        path = {this.props.location.pathname}
                        signOut = {this.signOut}
                         drawerClickHandler={this.drawerToggleClickHandler} />
                <SideDrawer click = {this.drawerToggleClickHandler} signOut = {this.signOut} show={this.state.sideDrawerOpen} />

                {backdrop}
            </div>

        <main style={{marginTop: '1px'}}>
            <div className="App">

                <Switch>
                    <Route exact path ='/' render = {MyHome}/>
                    <Route path='/profile' component = {Profile}/>
                </Switch>


            </div>
        </main>

        </div>
    );
export default  withAuthenticator(App, false);
  }
}

The problem is that the Route with the MyHome component throws this error: console logs with error and debug code from Home render.

The Home component is huge so I`ll include just the relevant code here

import React, { Component } from 'react';
import Auth from '@aws-amplify/auth';
import { API } from 'aws-amplify';
import ProfileRedirect from "./components/ProfileRedirect";
import LoadingAnimation from './components/LoadingAnimation';
import ReadingSpeed from "./components/ReadingSpeed";
import './Tags.css';
import Articles from "./components/Articles";
import { CSSTransitionGroup } from 'react-transition-group'
import FilterArea from './components/FilterArea';
import "react-datepicker/dist/react-datepicker.css";
import FilterDrop from './components/FilterDrop';
import FilterDrawer from './components/FilterDrawer';
import { withRouter } from "react-router";

let apiName = 'userApi';
let path = '/users/';

class Home extends Component {
    constructor(props){
        super(props);
        this.state = {
            isLoading: true,
            firstLogIn: true,
            filterDrawerOpen:false,
            user :{
                phone:"",
                readingSpeed:0,
                email:"",
                username:"",
                articles: [],
                interests: [],
                saved:[],
                filters:{
                    minutes:null,
                    authors:[],
                    sources:[],
                    minDate:{},
                    selectedInterests:[],
                    selectedDate:{}
                }
            }
        }

        this.dateFilter = this.dateFilter.bind(this)



    }

    async componentDidMount(){

        let userEntry;
        let date = new Date();
        date.setMonth(date.getMonth()-1)



        // const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
        const loggedUser = await Auth.currentAuthenticatedUser();

        userEntry = await API.get(apiName,path + loggedUser.username);

        if(userEntry.hasOwnProperty("userName")){
            let uniqueResults;
            let results = await this.callDatabase(userEntry)

            uniqueResults = results.reduce(function (p, c) {
                if (!p.some(function (el) {return (el.title === c.title && el.author === c.author);}))
                    p.push(c);
                return p;
            }, []);

            this.setState({
                isLoading:false,
                firstLogIn:false,
                filterDrawerOpen:false,
                user : {
                    phone:userEntry.userName,
                    readingSpeed:userEntry.readingSpeed,
                    email:userEntry.userEmail,
                    username:userEntry.userName,
                    articles: uniqueResults,
                    interests:userEntry.userInterests,
                    saved: userEntry.savedArticles,
                    filters:{
                        minutes:null,
                        authors:[],
                        sources:[],
                        minDate:date,
                        selectedDate:{},
                        selectedInterests:[]
                    }
                }
            })

        }else {
            this.setState({
                isLoading:false
            })
        }


    }

    async callDatabase (userEntry,sources,freeMode){...}


    authorFilter = selected => {...}

    sourceFilter = selected => {...}

    interestFilter = selected => {...}

    minutesFilter(value) {...}

    componentWillReceiveProps(newProps) {
        if(newProps.toggleFilter !== this.props.toggleFilter){
          this.filterToggleClickHandler();
        }
    }

    filterToggleClickHandler = () => {...}


    filterDropClickHandler = () => {...}

    dateFilter(selected) {...}

    generateOptions = filter => {...}

    async updateDataBase(readingSpeed){...}

    render() {
        let filterdrop;
        if(this.state.filterDrawerOpen) {
            filterdrop = <FilterDrop click = {this.filterDropClickHandler}/>
        }
        console.log(this.state)
        const stillLoading = () => {
            return (
                <div className="loading">
                    <LoadingAnimation
                        type = {"spinningBubbles"}
                        color = {"aqua"}
                    />
                </div>);
        }


        const articles =  (filterA, filterS, filterI, filterM) => {

            let articles = this.state.user.articles;
            let newDate = this.state.user.filters.selectedDate;
            let readingTime = this.state.user.readingSpeed;
            let check;
            if(newDate === null){
                check = true
            }else {
                check= Object.entries(newDate).length === 0 && newDate.constructor === Object
            }

            if(!check){
                articles =  this.checkDate(newDate,articles)
            }

            if(filterA.length){
                articles = this.checkAuthors(filterA,articles)
            }

            if(filterS.length){
                articles = this.checkSource(filterS,articles)
            }

            if(filterI.length){
                articles = this.checkInterest(filterI,articles)
            }
            if(!(filterM === null) && filterM!==0){
                articles = this.checkMinutes(filterM,readingTime,articles)
            }

            return(
                <div className="wrapper">
                    {
                        articles.map(function(article) {

                            return (
                                <Articles
                                    article = {article}
                                    key = {article.id}
                                />
                            )

                        })}
                </div> );





        }

        if(this.state.isLoading){
            return (
                stillLoading()
            );


        }else if(!this.state.firstLogIn && this.state.user.articles.length>0 && this.state.user.readingSpeed >0){
    console.log("Not loading, display articles")

            return (
                <CSSTransitionGroup
                    transitionName="example"
                    transitionAppear={true}
                    transitionAppearTimeout={1000}
                    transitionEnter={false}
                    transitionLeave={false}>

                    {this.filtersArea()}
                    {filterdrop}
                    {articles(this.state.user.filters.authors,this.state.user.filters.sources,
                        this.state.user.filters.selectedInterests,this.state.user.filters.minutes)}

                </CSSTransitionGroup>
            );
        }else if(this.state.firstLogIn || this.state.user.readingSpeed === 0){
            return(
                <ReadingSpeed updateDb = {this.updateDataBase.bind(this)}/>
            );
        }
        else if(this.state.user.interests.length === 0){
            return(
                <div>
                    <ProfileRedirect/>
                </div>
            );
        }else return null;

    }
}
export default Home;

The debug code in console.log("Not loading, display articles") in the Home component render is displayed in the console as can be seen here

debug code

but the component does not render.

Here is the full code for App.js

import React, { Component } from 'react';
import { library } from '@fortawesome/fontawesome-svg-core'
import './App.css';
import awsmobile from './aws-exports';
import { withAuthenticator } from 'aws-amplify-react';
import {Route, Switch, Link} from 'react-router-dom';
import Auth from '@aws-amplify/auth';
import Profile from './Profile';
import Home from './Home';
import Amplify, { API } from 'aws-amplify';
import Toolbar from './components/Toolbar';
import SideDrawer from './components/SideDrawer';
import Backdrop from './components/Backdrop';
import {faCheck} from "@fortawesome/free-solid-svg-icons/faCheck";
import {faSave} from "@fortawesome/free-solid-svg-icons/faSave";
import {faTrashAlt} from "@fortawesome/free-solid-svg-icons/faTrashAlt";
import {faExternalLinkAlt} from "@fortawesome/free-solid-svg-icons/faExternalLinkAlt";
import {faSignOutAlt} from "@fortawesome/free-solid-svg-icons/faSignOutAlt";
import {faUserCircle} from "@fortawesome/free-solid-svg-icons/faUserCircle";
import {faHome} from "@fortawesome/free-solid-svg-icons/faHome";
import {faSort} from "@fortawesome/free-solid-svg-icons/faSort";

library.add(faCheck)
library.add(faSave)
library.add(faTrashAlt)
library.add(faExternalLinkAlt)
library.add(faSignOutAlt)
library.add(faUserCircle)
library.add(faHome)
library.add(faSort)


//TODO
// Add Bloomberg API, The Sun, Mail online
// Make the nav bar come back when scroll wheel up
// Add change password and email adress in profile -check for mobile friendlyness

let apiName = 'userApi';
let path = '/users/';

Amplify.configure(awsmobile);

class App extends Component {
    constructor(props){
        super(props);
        this.state = {
            sideDrawerOpen:false,
            filterDrawerOpen:false,
            user:{}

        };
    }

    drawerToggleClickHandler = () => {
        this.setState((prevState) => {
            return {
                sideDrawerOpen: !prevState.sideDrawerOpen,
                filterDrawerOpen:false,
            };
        });
    };

    filterToggleClickHandler = () => {
        this.setState((prevState) => {
            return {filterDrawerOpen: !prevState.filterDrawerOpen,
                sideDrawerOpen: false};
        })
    }

    backdropClickHandler = () => {
        this.setState({sideDrawerOpen: false});
    };


    signOut = () => {
        Auth.signOut().then(() => {
            this.props.onStateChange('SignedOut');
        });
    }


    render() {

        let MyHome = (props) => {
            return(
                <Home {...props} toggleFilter={this.state.filterDrawerOpen}/>
            )
        }
        console.log("Mue")
        let backdrop;
        if (this.state.sideDrawerOpen) {
            backdrop = <Backdrop click={this.backdropClickHandler} />
        }

        return (
            <div className="container-fluid">

                <div className="row">
                    <Toolbar
                        filterClickHandler = {this.filterToggleClickHandler}
                        path = {this.props.location.pathname}
                        signOut = {this.signOut}
                        drawerClickHandler={this.drawerToggleClickHandler} />
                    <SideDrawer click = {this.drawerToggleClickHandler} signOut = {this.signOut} show={this.state.sideDrawerOpen} />

                    {backdrop}
                </div>

                <main style={{marginTop: '1px'}}>
                    <div className="App">

                        <Switch>
                            <Route exact path ='/' render = {MyHome}/>
                            <Route path='/profile' component = {Profile}/>
                        </Switch>


                    </div>
                </main>



            </div>
        );
    }
}

export default  withAuthenticator(App, false);

And index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import 'bootstrap/dist/css/bootstrap.css';
import {BrowserRouter as Router, Route} from 'react-router-dom';



ReactDOM.render(
    <Router>
        <Route path='/' render={(props )=> <App {...props}/>}/>
    </Router>,




    document.getElementById('root'));


serviceWorker.unregister();

What am I missing?

1
I know it would be lacking props but, if you did this: <Route exact path ='/' render = {Home}/> instead of using MyHome, would it work? - go_diego

1 Answers

0
votes

The render props in react-router is supposed to be a function : Render props

Use either of the two following lines to fix your code:

<Route exact path ='/' render={() => <MyHome/>}/>

<Route exact path ='/' component={<MyHome}/>