React - Get Div Element from another Component

Viewed 3018

My Objective is to make a simple open and close menu in React. Im used to vannila javascript where i can use getElementById to get my elements and store them in a variable, and do whatever i want whit them. Now im trying to do that whit react, but its getting a little dificult, i have try to use ref.

So this is my menu, i want to click on the button and hide the menu and show the content, that is my objective.

import React, { Component } from 'react';
import { Grid, Row, Col } from 'react-flexbox-grid';

class Menu extends Component {

  render() {
  function handleClick(e) {
    var mobileContainer = this.refs.mobileContent1;   
    console.log(mobileContainer);
  }

    return (
      <Grid fluid>
      <div className="menuContent">
        <Row center="xs">
          <Col xs={12}>
            <span href="" className="button" onClick={handleClick}>Hello, world!</span>
          </Col>                 
        </Row>
        </div>
      </Grid>
    );
  }


}

export default Menu;

When i console log mobileContainer i get this is undefined

This is my content component

import React, { Component } from 'react';
import { Grid, Row, Col } from 'react-flexbox-grid';

class MobileContent extends Component {

  render() {
    return (
      <Grid fluid>
        <div className="mobileContent" ref="mobileContent1">
          <Row center="xs">
            <Col xs={12}>
              <span className="button">Hello, world!</span>
              <span className="close">X</span>              
            </Col>                 
          </Row>
        </div>
      </Grid>
    );
  }
}

export default MobileContent;

Thanks for the Help

2 Answers

First of all you shouldn't define your click handler handleClick inside the render function, it will get created again and again whenever your render is called.

Now the reason for the error is that you haven't bind your function to this.

Change your code to something like this.

class Menu extends Component {
 constructor (props) {
  super(props);
  // bind the handler
  this.handleClick = this.handleClick.bind(this);
 }

 // you should define your function here
 handleClick() {
 ...
 }

 render(){
 .....
 }
}

I'd suggest you to use the internal state of your component to menage the menu instead of ref

    class Menu extends Component {
    constructor(props) {
        super(props);
        this.state = {
            isOpen: false
        };
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick(e) {
        e.preventDefault();
        this.setState(function(prevState){
            return {isOpen: !prevState.isOpen}
        });
        // Passing in a function into setState instead of an object will give you a reliable value for your component’s state and props.
    }
    render() {

        return (
            <Grid fluid>
                <div className="menuContent">
                    <Row center="xs">
                        <Col xs={12}>
                            <span href="" className="button" onClick={handleClick}>Hello, world!</span>
                            <MobileContent isOpen={this.state.isOpen} />
                        </Col>
                    </Row>
                </div>
            </Grid>
        );
    }
}

class MobileContent extends Component {

  render() {
    if (this.props.isOpen) {
        return (
            <Grid fluid>
                <div className="mobileContent" ref="mobileContent1">
                <Row center="xs">
                    <Col xs={12}>
                    <span className="button">Hello, world!</span>
                    <span className="close">X</span>              
                    </Col>                 
                </Row>
                </div>
            </Grid>
        );
    }
    return null;
  }
}

export default MobileContent;

Basically use the state to check if you need to render something or not. This is just the basic, you can do whatever you want with it: adding animations, reorganize you code etc...

In React the data flows fdown and a component may choose to pass its state down as props to its child components.

You have to think in React and not in jQuery way. Check this page out: https://reactjs.org/docs/thinking-in-react.html

Hope it helps :)

Related