index
index

Reputation: 3727

Show/Hide components in ReactJS

We have been experiencing some problems in using react now but it kinda boils to one part of how we have been using react.

How should we have been showing/hiding child components?

This is how we have coded it (this are only snippets of our components)...

_click: function() {
  if ($('#add-here').is(':empty'))
    React.render(<Child />, $('#add-here')[0]);
  else
    React.unmountComponentAtNode($('#add-here')[0]);
},
render: function() {
  return(
    <div>
      <div onClick={this._click}>Parent - click me to add child</div>
      <div id="add-here"></div>
    </div>
  )
}

and lately I've been reading examples like it should've been somewhere along this lines:

getInitialState: function () {
  return { showChild: false };
},
_click: function() {
  this.setState({showChild: !this.state.showChild});
},
render: function() {
  return(
    <div>
      <div onClick={this._click}>Parent - click me to add child</div>
      {this.state.showChild ? <Child /> : null}
    </div>
  )
}

Should I have been using that React.render()? It seems to stop various things like shouldComponentUpdate to cascade to child and things like e.stopPropagation...

Upvotes: 36

Views: 88022

Answers (2)

Lars Blumberg
Lars Blumberg

Reputation: 21441

I've provided a working example that follows your second approach. Updating the component's state is the preferred way to show/hide children.

Given you have this container:

<div id="container">
</div>

you can either use modern Javascript (ES6, first example) or classic JavaScript (ES5, second example) to implement the component logic:

Show/hide components using ES6

Try this demo live on JSFiddle

class Child extends React.Component {
  render() {
    return (<div>I'm the child</div>);
  }
}

class ShowHide extends React.Component {
  constructor() {
    super();
    this.state = {
      childVisible: false
    }
  }

  render() {
    return (
      <div>
        <div onClick={() => this.onClick()}>
          Parent - click me to show/hide my child
        </div>
        {
          this.state.childVisible
            ? <Child />
            : null
        }
      </div>
    )
  }

  onClick() {
    this.setState(prevState => ({ childVisible: !prevState.childVisible }));
  }
};

React.render(<ShowHide />, document.getElementById('container'));

Show/hide components using ES5

Try this demo live on JSFiddle

var Child = React.createClass({
  render: function() {
    return (<div>I'm the child</div>);
  }
});

var ShowHide = React.createClass({
  getInitialState: function () {
    return { childVisible: false };
  },

  render: function() {
    return (
      <div>
        <div onClick={this.onClick}>
          Parent - click me to show/hide my child
        </div>
        {
          this.state.childVisible
            ? <Child />
            : null
        }
      </div>
    )
  },

  onClick: function() {
    this.setState({childVisible: !this.state.childVisible});
  }
});

React.render(<ShowHide />, document.body);

Upvotes: 66

arvind grey
arvind grey

Reputation: 160

    /* eslint-disable jsx-a11y/img-has-alt,class-methods-use-this */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import todoStyle from 'src/style/todo-style.scss';
import { Router, Route, hashHistory as history } from 'react-router';
import Myaccount from 'src/components/myaccount.jsx';

export default class Headermenu extends Component {

  constructor(){
  super();

  // Initial state
  this.state = { open: false };

}

toggle() {
  this.setState({
    open: !this.state.open
  });
}

  componentdidMount() {
    this.menuclickevent = this.menuclickevent.bind(this);
    this.collapse = this.collapse.bind(this);
    this.myaccount = this.myaccount.bind(this);
    this.logout = this.logout.bind(this);
  }

  render() {
    return (
      <div>

        <div style={{ textAlign: 'center', marginTop: '10px' }} id="menudiv" onBlur={this.collapse}>
          <button onClick={this.toggle.bind(this)} > Menu </button>

          <div id="demo" className={"collapse" + (this.state.open ? ' in' : '')}>
            <label className="menu_items" onClick={this.myaccount}>MyAccount</label>
            <div onClick={this.logout}>
              Logout
            </div>
          </div>

        </div>
      </div>
    );
  }

  menuclickevent() {
    const listmenu = document.getElementById('listmenu');
    listmenu.style.display = 'block';
  }



  logout() {
    console.log('Logout');
  }
  myaccount() {
    history.push('/myaccount');
    window.location.reload();

  }


}

Upvotes: 0

Related Questions