0

Here's my App.js

import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import {BrowserRouter as Router} from 'react-router-dom';
import Navbar from "./components/nav";
import firebase from './firebase';
import Questions from './components/questions';
import Stuff from './components/stuff';
class App extends Component {
    constructor(p) {
        super(p);
        this.state = {user: null}
    }

    render() {
        return (
            <div className="App">
                <Navbar/>
                {this.state.user ? <Questions/> : <Stuff/>}
            </div>
        );
    }
}

export default App;

The idea is, it should render the navbar, and if the user is logged in, it should render Questions element, and otherwise, render something else.

Here's my <Navbar/> element:

import React from 'react';
import {Navbar as Bar, Nav, NavItem, Modal, Button, FormControl} from 'react-bootstrap';
import {BrowserRouter as Router, Link, Route} from 'react-router-dom';
import firebase, {auth} from '../firebase';

class Navbar extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
        this.login = this.login.bind(this);
        this.logout = this.logout.bind(this);
        this.openLogin = this.openLogin.bind(this);
        this.handleClose = this.handleClose.bind(this);
    }

    componentDidMount() {
        auth.onAuthStateChanged((user) => {
            if (user) {
                this.setState({user});
            }
        });
    }

    logout() {
        auth.signOut()
            .then(() => {
                this.setState({
                    user: null
                });
            });
    }

    login() {
        var email = document.getElementById('email').value;
        var password = document.getElementById('password').value;
        auth.signInWithEmailAndPassword(email, password)
            .then(result => {
                    const user = result.user;
                    this.setState({user});
                    document.getElementById('close').click();
                }
            ).catch(e => console.log(e));
    }

    openLogin() {
        this.setState({show: true});
    }

    handleClose() {
        this.setState({show: false});
    }

    render() {
        return (
            <React.Fragment>
                <Router>
                    <Bar>
                        <Bar.Header>
                            <Bar.Brand>
                                <a href="/home">UczIchApp</a>
                                {/*<Route path='path' component=""/>*/}
                            </Bar.Brand>
                            <Bar.Brand>

                            </Bar.Brand>
                        </Bar.Header>
                        <Nav>
                            {
                                this.state.user ?
                                    <NavItem onClick={this.logout}>Wyloguj się</NavItem>
                                    :
                                    <NavItem onClick={this.openLogin}>Zaloguj się</NavItem>
                            }
                        </Nav>
                    </Bar>
                </Router>
                <Modal show={this.state.show} onHide={this.handleClose}>
                    <Modal.Header closeButton>
                        <Modal.Title>Modal heading</Modal.Title>
                    </Modal.Header>
                    <Modal.Body>
                        <form>
                            <FormControl
                                id="email"
                                type="email"
                                label="Email address"
                                placeholder="Enter email"
                            />
                            <FormControl id="password" label="Password" type="password"/>
                            <Button onClick={this.login}>Zaloguj</Button>
                        </form>
                    </Modal.Body>
                    <Modal.Footer>
                        <Button id="close" onClick={this.handleClose}>Close</Button>
                    </Modal.Footer>
                </Modal>
            </React.Fragment>
        )
    }
}

export default Navbar;

So I want to change the interior in the <App/> element, based on the user state changed in the <Navbar/> element. How can I do that? Right now the state is unavailable in <App.js/>

Alex Ironside
  • 4,658
  • 11
  • 59
  • 119
  • 1
    this question will help you redesign your app better, https://stackoverflow.com/questions/46594900/reactjs-lifting-state-up-vs-keeping-a-local-state/47349693#47349693 – Shubham Khatri May 29 '18 at 10:55

2 Answers2

1

Make a function checkUserState in your App Component

 constructor(p) {
    super(p);
    this.state = {user: null}
    this.checkUserState= this.checkUserState.bind(this);
}

checkUserState(user){
    this.seState({user});
}

And then pass props in Navbar component as

 <Navbar {...this}/>

Inside Navbar Component where you set state, do this

this.setState({
        user: null
    },function(){
        this.props.checkUserState(this.state.user)
    });

Since you will need to go reverse as Navbar is a child component.

Manoz
  • 6,507
  • 13
  • 68
  • 114
0

It looks like you need to globally handle the state of the app. You could try using redux to manage the state of that app. or you can just pass a function as a prop to the nav from your parent component and that function can handle state

Js fiddle example

const Nav = ({ handleClick }) => {
    return (<button onClick={handleClick}>hello world</button>);
}

class HelloMessage extends React.Component {
    constructor(props){
    super(props);
    this.state = {
    checked: false
    }
  }
    handleClick = (e) => {
    e.preventDefault();
        this.setState({checked: !this.state.checked});
  }
  render() {
    return (
      <div>
      <Nav handleClick={this.handleClick}/>
      <p><b>status:</b> {this.state.checked ? 'checked' : 'unchecked'}</p>
      </div>
    );
  }
}

ReactDOM.render(
  <HelloMessage name="Taylor" />,
  document.getElementById('app')
);
Trevor Joseph
  • 749
  • 5
  • 3