0

This is my code:

NavigationComponent - this is my navigation. I want the button clicked here to fire up a method from the child.

class NavigationComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
    }

    componentWillMount() {
        firebase.auth().onAuthStateChanged(user => {
            if (user) {
                console.log(user);
                this.setState(
                    {
                        user: user
                    }, () => this.props.checkUserState(this.state.user)
                );
            }
        });
    }

    render() {
        return (
            <BrowserRouter>
                <React.Fragment>
                    <Navbar>
                        <Navbar.Header>
                            <Navbar.Brand>
                                <Link id='home' to="/">UczIchApp</Link>
                            </Navbar.Brand>
                        </Navbar.Header>
                        <Nav>
                            <LinkContainer id='about' to='/about'>
                                <NavItem>O nas</NavItem>
                            </LinkContainer>
                            {
                                this.state.user ?
                                    <React.Fragment>
                                        <LinkContainer id="questions" to='/questions'>
                                            <NavItem>Zadania</NavItem>
                                        </LinkContainer>
                                        <NavItem onClick={Want to use it here}>Wyloguj się</NavItem>
                                    </React.Fragment>
                                    :
                                    <NavItem onClick={And here}>Zaloguj się</NavItem>
                            }
                        </Nav>
                    </Navbar>
                    <Switch>
                        <Route exact path="/about" component={AboutComponent}/>
                        <Route exact path="/questions" component={QuestionsComponent}/>
                        <Route exact path="/" component={HomeComponent}/>
                        <Route path='/question/:id' component={QuestionComponent}/>
                    </Switch>
                </React.Fragment>
            </BrowserRouter>
        )
    }
}

LogoutComponent - I want a method from this component to be fired up

export default class LogoutComponent extends react.Component {
    constructor(p) {
        super(p);
        this.logout = this.logout.bind(this);
        console.log('tada');
    }

    logout() {
        console.log('got here');
        firebase
            .auth()
            .signOut()
            .then(() => {
                this.setState({
                    user: null
                }, function () {
                    this.props.checkUserState(this.state.user)
                });
            });
    }
}

What I want to do, is to use the logout() function when the button on the navbar is clicked. The problem is I have no idea how to reference it.

I tried something like this LogoutComponent.logout, but no luck. If it's not possible, how could I solve this?

Alex Ironside
  • 4,658
  • 11
  • 59
  • 119

1 Answers1

1

This can be done by using React refs, and a method on the child component.

parent.js

constructor() {
  super();
  this.child_ref = null;
}

createChildRef(DOMElement) {
  this.child_ref = DOMElement;
}

respondToSomeEvent() {
  if (this.child_ref) {
    this.child_ref.somePublicMethod();
  }
}

render() {
  return (
    <ChildComponent ref={this.createChildRef} />
  )
}

child.js

class ChildComponent extends React.Component {
  somePublicMethod() {
    // The parent can call this method through the React ref
  }
}

Sometimes it is necessary to do this, based on the architecture of your application, but you should look into passing around an EventEmitter instance instead, so that your components can respond to changes outside of state that is stored in React.

ouni
  • 3,233
  • 3
  • 15
  • 21
  • What is `DOMElement` here? – Alex Ironside Jun 07 '18 at 06:56
  • It’s an instance of the rendered child React component on the page: you can use both DOM methods on it, as if it were an HTML element, and you can call methods from the React component class that generated it. – ouni Jun 07 '18 at 11:59