setState inside onAuthStateChange is not working

Viewed 89

When I click on the login button it redirects to login component instead of /home. That is happening because inside the onAuthStateChange method when I try to change the state of user it doesn't work, (don't know why). Can somebody point out the problem?

Also I'm trying to render a bunch of cards from fetching json froma api, but that is also not working, there are no errors it items property in my state remains null when the app renders the cards.

This is my app.js file:

import { Component } from 'react';
import { BrowserRouter } from 'react-router-dom';
import { Switch, Route, Redirect } from 'react-router-dom';
import Login from './components/Login';
import Home from './components/Home';
import fireBase from './config/firebase';


class App extends Component {
    constructor(props){
        super(props);
        this.state={
          user : {}
        }
    }
    componentDidMount(){
        this.authListener();
    }
    authListener(){
        fireBase.auth().onAuthStateChanged((User)=>{
            if(User){
                this.setState({user: User})
                console.log(this.state.user);
            }
            else{
                this.setState({user : null})
            }
        })
    }
    render(){
        
        const HomePage = () => {
            return(
                (this.state.user) ? (<Home user={this.state.user}/>) : (<Login/>)
            );
        }
        
        return (
        <BrowserRouter>
            <div className="App">
                    <Switch>
                        <Route exact path="/"><Login /></Route>
                        <Route exact path="/login"><Login /></Route>
                        <Route exact path="/home" component={HomePage}/>
                        <Redirect to="/login" />
                    </Switch>
            </div>
        </BrowserRouter>
        );
    }
}

export default App;

My Login page looks like this:

import React, { Component } from 'react';
import { Button, Navbar, NavbarBrand, Nav, NavbarToggler, Collapse, NavItem ,Card, CardImg, CardText, CardBody, CardTitle, Jumbotron } from 'reactstrap';
import fireBase from '../config/firebase';



function itemList() { this.state.items.map((item) => {
        return (
            <div className="row">
                <div key={item.id} className="col-12 col-md-5 m-1">
                    <Card>
                        <CardImg width="100%" src={item.thumbnailUrl} alt={item.title} />
                        <CardBody>
                            <CardTitle>{item.title}</CardTitle>
                            <CardText>quia et suscipit\nsuscipit recusandae consequuntur 
                                    expedita et cum\nreprehenderit molestiae ut ut quas
                                    totam\nnostrum rerum est autem sunt rem eveniet architecto
                            </CardText>
                        </CardBody>
                    </Card>
                </div>
            </div>
        );
    });
}

class Home extends Component{
    _isMounted=false;

    constructor(props){
        super(props);
        this.state={
            items: [],
            isNavOpen:false
        }
        this.getItems = this.getItems.bind(this);
        this.toggleNav = this.toggleNav.bind(this);
        
    }
    
    toggleNav() {
        this.setState({
            isNavOpen: !this.state.isNavOpen
        });
    }
    
    componentDidMount(){
        this._isMounted=true;
        this.getItems('https://jsonplaceholder.typicode.com/photos')
        .then(data => JSON.stringify(data))
        .then(
            data => {
                if(this._isMounted)
                this.setState({items: data.slice(0,5)})
            }
        )
        .then(()=>console.log(this.state.items))
        .catch(err => console.log(err));
    }
    
    componentWillUnmount(){
        this._isMounted=false;
    }


    handleLogout(e){
        fireBase.auth().signOut();
    }
    
    
    render(){
        return(
            <React.Fragment>
                <Navbar dark expand="md">
                    <div className="container">
                        <NavbarToggler onClick={this.toggleNav} />
                        <NavbarBrand className="mr-auto" href="/">
                            <img src="favicon.ico" height="30" width="41" alt="favicon" />
                        </NavbarBrand>
                        <Collapse isOpen={this.state.isNavOpen} navbar>
                            <Nav className="ml-auto" navbar>
                                <NavItem className="float-right">
                                        <div className="navbar-text mr-3">Hello User!</div>
                                        <Button outline onClick={this.handleLogout}>
                                            <span className="fa fa-sign-out fa-lg"></span> Logout
                                        </Button>
                                </NavItem>
                            </Nav>
                        </Collapse>
                    </div>
                </Navbar>
            <Jumbotron>
                <div className="container">
                    <div className="row row-header">
                        <div className="col-12 col-md-8">
                            <h1 className="m-10">Welcome to Dashboard</h1>
                        </div>
                    </div>
                </div>
            </Jumbotron>
            <Jumbotron>
            <div className="container">
                {itemList}
            </div>
            </Jumbotron>
            </React.Fragment>
        );
    }
    
    getItems = async (endpoint) => {
        const res = await fetch(endpoint);
        const data = await res.json();
        console.log(data.slice(0,5));
        return data;
    }
}

export default Home;
1 Answers

Because state only has new value when component re render. So should put console.log inside render method

Related