805

I am messing around with React.js for the first time and cannot find a way to show or hide something on a page via click event. I am not loading any other library to the page, so I am looking for some native way using the React library. This is what I have so far. I would like to show the results div when the click event fires.

var Search= React.createClass({
    handleClick: function (event) {
        console.log(this.prop);
    },
    render: function () {
        return (
            <div className="date-range">
                <input type="submit" value="Search" onClick={this.handleClick} />
            </div>
        );
    }
});

var Results = React.createClass({
    render: function () {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

React.renderComponent(<Search /> , document.body);
Damjan Pavlica
  • 31,277
  • 10
  • 71
  • 76
user1725382
  • 8,242
  • 3
  • 14
  • 18
  • 16
    The accepted comment uses novel tech to do what existing tech at the native level can do both more easily, faster, and shareably with other languages and libraries. Handling this with standard CSS is almost certainly the better answer. – John Haugeland Jan 30 '15 at 00:43
  • 13
    @JohnHaugeland, best answer when using React framework is the accepted answer, going all React style, which has cleanup functions which in some cases you must do. It's not good practice to have components just hiding in the dark. If you mix stuff you are better going all native which is always faster than anything else. – Claudiu Hojda May 27 '15 at 12:06
  • 9
    No, it really isn't. Using react to reinvent CSS is a bad idea. – John Haugeland May 29 '15 at 18:08
  • 12
    Besides, you seem to have completely missed the point of what I said, which was to use CSS to hide and show the element, rather than to use React to physically remove it. You *can* use React to use CSS to hide and show the element just as easily:
    .
    – John Haugeland May 29 '15 at 18:09
  • 6
    @ClaudiuHojda having components hide in the dark is actually very good practice in some cases, I'm thinking of responsive navigation, where you need the links to remain in the HTML even if they're hidden with css – Toni Leigh Dec 03 '15 at 07:50
  • This tutorial helped me https://youtu.be/Mo2_UPkZjJU – Prem Mar 13 '17 at 19:44
  • This is a good tutorial for using the state and ternary operator: https://noobieprogrammer.blogspot.com/2020/09/reactjs-how-to-create-toggle-showhide.html – doppelgunner Sep 26 '20 at 12:33

34 Answers34

822

React circa 2020

In the onClick callback, call the state hook's setter function to update the state and re-render:

const Search = () => {
  const [showResults, setShowResults] = React.useState(false)
  const onClick = () => setShowResults(true)
  return (
    <div>
      <input type="submit" value="Search" onClick={onClick} />
      { showResults ? <Results /> : null }
    </div>
  )
}

const Results = () => (
  <div id="results" className="search-results">
    Some Results
  </div>
)

ReactDOM.render(<Search />, document.querySelector("#container"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>

<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>

JSFiddle

React circa 2014

The key is to update the state of the component in the click handler using setState. When the state changes get applied, the render method gets called again with the new state:

var Search = React.createClass({
    getInitialState: function() {
        return { showResults: false };
    },
    onClick: function() {
        this.setState({ showResults: true });
    },
    render: function() {
        return (
            <div>
                <input type="submit" value="Search" onClick={this.onClick} />
                { this.state.showResults ? <Results /> : null }
            </div>
        );
    }
});

var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

ReactDOM.render( <Search /> , document.getElementById('container'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.min.js"></script>

<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>

JSFiddle

Douglas
  • 36,802
  • 9
  • 76
  • 89
  • 4
    Yes, good point about state vs props. A better way to do this whould be like in the tutorial here, where the search bar and the results table are siblings instead of putting Results inside Search: http://facebook.github.io/react/docs/thinking-in-react.html – Douglas Jul 02 '14 at 15:58
  • 68
    As noted in the other answer, insertion/deletion are much slower than simple class masking. – John Haugeland Jan 30 '15 at 00:42
  • 6
    I think Johns comments need reviewing. I went with the intended answer and that was neat and 'felt' more react like. However I was unable to set initial states and anything useful on an unmounted component. I am looking at using css to hide things instead. Listeners on unmounted components will silently fail this has caused me big time loss today. – landed Feb 25 '16 at 12:25
  • 2
    Does that mean react will rerender the component when the style changes ( is set to show/hide ) !? – alex Nov 09 '16 at 06:55
  • 1
    @Douglas unless I missed it, this way does not allow toggling back to the original. I guess the OP may not have wanted it but how can I include this? – The worm Nov 15 '16 at 10:53
  • Note to everyone trying to use it - this example is extremely outdated. – Adam Pietrasiak Apr 09 '20 at 19:32
  • You need to be aware here that component will be re rendered always whenever showResult chages. – Bojan Golubovic Oct 22 '20 at 11:39
  • 1
    @BojanGolubovic, yes, that's true, Results will be rendered when showResults gets set to true. In this example it starts off hidden, so it isn't rendered until it is shown. Whether it is better to pre-render it hidden and then show it on click or to delay rendering it until it is shown will depend on what the Results component does. For example, if the search results depend on what is typed into a search box, then only rendering it once the search term is known would be better. – Douglas Oct 29 '20 at 11:34
  • 6
    Instead of `{ showResults ? : null }` can do `{ showResults && }` – zwbetz Nov 16 '20 at 15:38
  • { !!somevar && } when somevar is not of type boolean. @zwbetz – Iceberg Aug 26 '21 at 01:25
  • @Iceberg - the var doesn't have to be a boolean, it's a truthy check. – zwbetz Aug 26 '21 at 17:40
  • @zwbetz `{ 0 &&

    foo

    }` will render 0 rather than

    foo

    , double exclamation on the somevar can avoid this type of issue.
    – Iceberg Aug 27 '21 at 07:32
  • @Iceberg - I stand corrected. Did not realize that 0 was an exception. For others, a snippet from the React docs: _One caveat is that some “falsy” values, such as the 0 number, are still rendered by React._ – zwbetz Sep 06 '21 at 04:40
  • there is two other Question also: 1-how can we have css transition property on that element while show/hide? 2-actually in this technique -->{ showResults ? : null }<-- it will delete that element, but what if we just need to just opacity:0 ? to add a transition? is there any other technique? – amir mohseni Nov 14 '21 at 18:05
308
<style type="text/css">
    .hidden { display:none; }
</style>
const Example = props => 
  <div className={props.shouldHide? 'hidden' : undefined}>Hello</div>
John Haugeland
  • 9,230
  • 3
  • 37
  • 40
  • 20
    It's better to conditionally return null as in Douglas's answer. That allows React to remove it from the DOM entirely. In your case the div & its contents are still in the DOM just not showing. This may have performance implications. – pmont Sep 07 '14 at 03:31
  • 171
    The performance implications are much worse for adding and removing a dom element than they are for hiding and showing it. I am aware of the difference between his approach and mine, and I believe that you have this exactly wrong. Please consider taking the time to define "performance implications" and then measure it. – John Haugeland Sep 07 '14 at 04:41
  • 2
    It's worth noting that he's also making other severe errors with performance implications, such as using state rather than props, which screws the diffing algorithm; keeping this in two controls, which massively increases DOM overhead; involving an onClick handler; et cetera. Please actually have numbers in hand before declaring someone else incorrect. – John Haugeland Sep 07 '14 at 04:43
  • 1
    That's an interesting perspective. For trivial cases you may be right, but as the DOM gets increasingly cluttered, reflows can kill performance. It's best to let the React engine do what it was designed to do and cull unneeded elements. I don't have numbers but defer to Peter Hunt's talks. As another example, Famous adds & removes elements at up to 60 times per second with no serious performance issues. – pmont Sep 08 '14 at 00:41
  • Reflows are guaranteed with add/remove, and likely (cachably deniable) with hide/show. The described difference does not exist. Remember to compare option 2 to option 1, rather than to nothing at all. (If you can add and remove at 60 fps without problems, then neither approach has a problem; conceptually, hide/show is correct here, not add/detatch.) Maybe more importantly, no standing criticism damns either approach, and this approach is at-least-as-fast probably-faster. Hence the call for definitions and measurements. – John Haugeland Sep 08 '14 at 01:35
  • 6
    "Reflows are guaranteed with add/remove" -- Not with absolutely positioned elements, which is how Famous gets its incredible performance. But you make a valid point on the metrics. – pmont Sep 08 '14 at 02:02
  • I had not considered absolutely (or fixedly) positioned elements. Thank you for pointing that out. – John Haugeland Sep 08 '14 at 04:29
  • 10
    for what it's worth, this is mentioned in the react docs here: http://facebook.github.io/react/docs/multiple-components.html#stateful-children – Brad Parks Sep 25 '14 at 09:45
  • Yep. Reflows are still guaranteed with almost every other add/remove; other than extremists like famous, my original position stands for essentially any normally structured website – John Haugeland Sep 25 '14 at 14:21
  • This approach also allows you to interact with things that aren't React in a meaningful way, such as leveraging CSS transitions. I very much feel like nobody's actually considering the alternative. – John Haugeland Sep 25 '14 at 14:22
  • 118
    So I just tested returning null vs. setting a hidden class with 161 fairly large dom nodes. It is significantly faster using a class than removing the node. – Jonathan Rowny Jan 29 '15 at 23:15
  • 6
    @JonathanRowny - sure is. Not surprising to me, either. Thanks for doing the heavy lifting. (The bit people tend to forget about relayout thrash is that there's at least one no matter what: the insertion. React can't fix that, only reduce a bunch to one. When it's a css toggle, the browser's native CSS impl can do the same thing, in native code.) – John Haugeland Jan 30 '15 at 00:41
  • Has anyone considered a situation where one repeatedly needs to trigger the "visibility"? Setting `display` to `none` and back sounds way more reasonable than repeatedly mounting/unmounting. Except for when one implements caching. (Or does React cache the instances in this situation by itself?) – Qwerty Sep 26 '17 at 19:47
  • Yes in many cases performance will be better by just not showing it, however for completeness, if the content being hidden expensively computes a view of the app state, hiding *can* be less performant than removing DOM nodes. In a nontrivial app, measuring performance and managing the view complexity are essential to knowing for sure. – Chris Mountford Dec 13 '21 at 04:12
192

Here is an alternative syntax for the ternary operator:

{ this.state.showMyComponent ? <MyComponent /> : null }

is equivalent to:

{ this.state.showMyComponent && <MyComponent /> }

Learn why


Also alternative syntax with display: 'none';

<MyComponent style={this.state.showMyComponent ? {} : { display: 'none' }} />

However, if you overuse display: 'none', this leads to DOM pollution and ultimately slows down your application.

StefanBob
  • 4,857
  • 2
  • 32
  • 38
Lyubomir
  • 19,615
  • 6
  • 55
  • 69
  • 6
    Warning! Use 'double ampersand(&&)' approach only for bool values. { this.state.myComponents.length && } will render 0, if myComponents empty array(for example) – Mega Proger Mar 22 '20 at 12:36
  • 2
    @MegaProger in such case cast to boolean with `!!` i.e. ```{ !!this.state.myComponents.length && }``` – Pawel Jan 18 '21 at 15:13
  • 2
    This is not in any sense an "alternative syntax for the ternary operator." This is buggy, and there are other places besides double negation of the opening clause where this will cause problems. – John Haugeland Apr 09 '21 at 14:38
  • 2
    The second example is a code smell, in my opinion – Alex W Apr 26 '21 at 18:20
120

Here is my approach.

import React, { useState } from 'react';

function ToggleBox({ title, children }) {
  const [isOpened, setIsOpened] = useState(false);

  function toggle() {
    setIsOpened(wasOpened => !wasOpened);
  }

  return (
    <div className="box">
      <div className="boxTitle" onClick={toggle}>
        {title}
      </div>
      {isOpened && (
        <div className="boxContent">
          {children}
        </div>
      )}
    </div>
  );
}

In code above, to achieve this, I'm using code like:

{opened && <SomeElement />}

That will render SomeElement only if opened is true. It works because of the way how JavaScript resolve logical conditions:

true && true && 2; // will output 2
true && false && 2; // will output false
true && 'some string'; // will output 'some string'
opened && <SomeElement />; // will output SomeElement if `opened` is true, will output false otherwise (and false will be ignored by react during rendering)
// be careful with 'falsy' values eg
const someValue = [];
someValue.length && <SomeElement /> // will output 0, which will be rednered by react
// it'll be better to:
someValue.length > 0 && <SomeElement /> // will render nothing as we cast the value to boolean

Reasons for using this approach instead of CSS 'display: none';

  • While it might be 'cheaper' to hide an element with CSS - in such case 'hidden' element is still 'alive' in react world (which might make it actually way more expensive)
    • it means that if props of the parent element (eg. <TabView>) will change - even if you see only one tab, all 5 tabs will get re-rendered
    • the hidden element might still have some lifecycle methods running - eg. it might fetch some data from the server after every update even tho it's not visible
    • the hidden element might crash the app if it'll receive incorrect data. It might happen as you can 'forget' about invisible nodes when updating the state
    • you might by mistake set wrong 'display' style when making element visible - eg. some div is 'display: flex' by default, but you'll set 'display: block' by mistake with display: invisible ? 'block' : 'none' which might break the layout
    • using someBoolean && <SomeNode /> is very simple to understand and reason about, especially if your logic related to displaying something or not gets complex
    • in many cases, you want to 'reset' element state when it re-appears. eg. you might have a slider that you want to set to initial position every time it's shown. (if that's desired behavior to keep previous element state, even if it's hidden, which IMO is rare - I'd indeed consider using CSS if remembering this state in a different way would be complicated)
Adam Pietrasiak
  • 12,773
  • 9
  • 78
  • 91
  • 2
    This is a great example! One small thing, boxContent should be className="boxContent" – Bhetzie Nov 21 '17 at 02:31
  • 10
    There is a bug right here: `this.setState({isOpened: !isOpened});`. Do not depend on the state itself, when you modify the state. Here is a good example: https://reactjs.org/docs/conditional-rendering.html#preventing-component-from-rendering So it should be: `this.setState( s => ({isOpened: !s.isOpened}) )`. Note the arrow function inside setState. – arcol Dec 28 '18 at 10:55
  • Do you have any source/benchmark/example confirming this "If you set display: none - element is still rendered by react and added to DOM - that can have bad impact on performance." ? – neiya Feb 04 '20 at 13:34
  • @neiya I don't. CSS might be more performant with small elements, but quite often you want to render optionally big parts of content eg. tab. Also, while some element is hidden with CSS - it's still alive in the react world. It means that it might update it's state, fetch some data etc which might be expensive and lead to unexpected behaviour. And it's IMO actually very simple to implement. – Adam Pietrasiak Apr 09 '20 at 19:21
  • ```Need small correction in setting up state``` const [isOpened, setIsOpened] = useState(false); const toggle= ()=> { setIsOpened(isOpened => !isOpened); } – R. Mahbub Feb 11 '23 at 12:20
20

with the newest version react 0.11 you can also just return null to have no content rendered.

Rendering to null

Edgar
  • 6,022
  • 8
  • 33
  • 66
squiddle
  • 1,259
  • 8
  • 17
  • Link-only responses should be posted as comments, not "answers". To qualify as an answer, please include relevant information from the linked page. If the page were to become unreachable, or if its contents were to change this response would become useless. All Answers on SO must be self sufficient, by not *requiring* an outside resource to read the solution. Also *exact* code necessary to solve the problem must be embedded in the answer, if the question is of the type that lends itself to a coded answer. – SherylHohman Oct 27 '21 at 16:03
  • Please update to include an example of "exact code necessary" to solve the OP's issue, as stated in SO guidelines. – SherylHohman Oct 27 '21 at 17:12
17

This is a nice way to make use of the virtual DOM:

class Toggle extends React.Component {
  state = {
    show: true,
  }

  toggle = () => this.setState((currentState) => ({show: !currentState.show}));

  render() {
    return (
      <div>
        <button onClick={this.toggle}>
          toggle: {this.state.show ? 'show' : 'hide'}
        </button>    
        {this.state.show && <div>Hi there</div>}
      </div>
     );
  }
}

Example here

Using React hooks:

const Toggle = () => {
  const [show, toggleShow] = React.useState(true);

  return (
    <div>
      <button
        onClick={() => toggleShow(!show)}
      >
        toggle: {show ? 'show' : 'hide'}
      </button>    
      {show && <div>Hi there</div>}
    </div>
  )
}

Example here

daniloprates
  • 574
  • 1
  • 5
  • 17
14

I created a small component that handles this for you: react-toggle-display

It sets the style attribute to display: none !important based on the hide or show props.

Example usage:

var ToggleDisplay = require('react-toggle-display');

var Search = React.createClass({
    getInitialState: function() {
        return { showResults: false };
    },
    onClick: function() {
        this.setState({ showResults: true });
    },
    render: function() {
        return (
            <div>
                <input type="submit" value="Search" onClick={this.onClick} />
                <ToggleDisplay show={this.state.showResults}>
                    <Results />
                </ToggleDisplay>
            </div>
        );
    }
});

var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

React.renderComponent(<Search />, document.body);
Edgar
  • 6,022
  • 8
  • 33
  • 66
ccnokes
  • 6,885
  • 5
  • 47
  • 54
13

There are several great answers already, but I don't think they've been explained very well and several of the methods given contain some gotchas that might trip people up. So I'm going to go over the three main ways (plus one off-topic option) to do this and explain the pros and cons. I'm mostly writing this because Option 1 was recommended a lot and there's a lot of potential issues with that option if not used correctly.

Option 1: Conditional Rendering in the parent.

I don't like this method unless you're only going to render the component one time and leave it there. The issue is it will cause react to create the component from scratch every time you toggle the visibility. Here's the example. LogoutButton or LoginButton are being conditionally rendered in the parent LoginControl. If you run this you'll notice the constructor is getting called on each button click. https://codepen.io/Kelnor/pen/LzPdpN?editors=1111

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;

    let button = null;
    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
  }
}

class LogoutButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created logout button');
  }
  render(){
    return (
      <button onClick={this.props.onClick}>
        Logout
      </button>
    );
  }
}

class LoginButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created login button');
  }
  render(){
    return (
      <button onClick={this.props.onClick}>
        Login
      </button>
    );
  }
}

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);

Now React is pretty quick at creating components from scratch. However, it still has to call your code when creating it. So if your constructor, componentDidMount, render, etc code is expensive, then it'll significantly slow down showing the component. It also means you cannot use this with stateful components where you want the state to be preserved when hidden (and restored when displayed.) The one advantage is that the hidden component isn't created at all until it's selected. So hidden components won't delay your initial page load. There may also be cases where you WANT a stateful component to reset when toggled. In which case this is your best option.

Option 2: Conditional Rendering in the child

This creates both components once. Then short circuits the rest of the render code if the component is hidden. You can also short circuit other logic in other methods using the visible prop. Notice the console.log in the codepen page. https://codepen.io/Kelnor/pen/YrKaWZ?editors=0011

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;
    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        <LoginButton isLoggedIn={isLoggedIn} onClick={this.handleLoginClick}/>
        <LogoutButton isLoggedIn={isLoggedIn} onClick={this.handleLogoutClick}/>
      </div>
    );
  }
}

class LogoutButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created logout button');
  }
  render(){
    if(!this.props.isLoggedIn){
      return null;
    }
    return (
      <button onClick={this.props.onClick}>
        Logout
      </button>
    );
  }
}

class LoginButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created login button');
  }
  render(){
    if(this.props.isLoggedIn){
      return null;
    }
    return (
      <button onClick={this.props.onClick}>
        Login
      </button>
    );
  }
}

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);

Now, if the initialization logic is quick and the children are stateless, then you won't see a difference in performance or functionality. However, why make React create a brand new component every toggle anyway? If the initialization is expensive however, Option 1 will run it every time you toggle a component which will slow the page down when switching. Option 2 will run all of the component's inits on first page load. Slowing down that first load. Should note again. If you're just showing the component one time based on a condition and not toggling it, or you want it to reset when toggledm, then Option 1 is fine and probably the best option.

If slow page load is a problem however, it means you've got expensive code in a lifecycle method and that's generally not a good idea. You can, and probably should, solve the slow page load by moving the expensive code out of the lifecycle methods. Move it to an async function that's kicked off by ComponentDidMount and have the callback put it in a state variable with setState(). If the state variable is null and the component is visible then have the render function return a placeholder. Otherwise render the data. That way the page will load quickly and populate the tabs as they load. You can also move the logic into the parent and push the results to the children as props. That way you can prioritize which tabs get loaded first. Or cache the results and only run the logic the first time a component is shown.

Option 3: Class Hiding

Class hiding is probably the easiest to implement. As mentioned you just create a CSS class with display: none and assign the class based on prop. The downside is the entire code of every hidden component is called and all hidden components are attached to the DOM. (Option 1 doesn't create the hidden components at all. And Option 2 short circuits unnecessary code when the component is hidden and removes the component from the DOM completely.) It appears this is faster at toggling visibility according some tests done by commenters on other answers but I can't speak to that.

Option 4: One component but change Props. Or maybe no component at all and cache HTML.

This one won't work for every application and it's off topic because it's not about hiding components, but it might be a better solution for some use cases than hiding. Let's say you have tabs. It might be possible to write one React Component and just use the props to change what's displayed in the tab. You could also save the JSX to state variables and use a prop to decide which JSX to return in the render function. If the JSX has to be generated then do it and cache it in the parent and send the correct one as a prop. Or generate in the child and cache it in the child's state and use props to select the active one.

Kelnor
  • 131
  • 1
  • 4
11

You set a boolean value in the state (e.g. 'show)', and then do:

var style = {};
if (!this.state.show) {
  style.display = 'none'
}

return <div style={style}>...</div>
Brigand
  • 84,529
  • 20
  • 165
  • 173
  • I tried this, but the click event did not switch the css to display block. I am lost on exactly how to accomplish it. Any additional tips? – user1725382 Jul 01 '14 at 18:16
  • 1
    This involves making active changes to the style rule table. It's much better to have a single existing rule that you can turn on and off, which is not part of the dynamic properties of the dom node. – John Haugeland Jan 30 '15 at 19:20
  • 1
    It really doesn't matter if you use a class or style here... you seem very worked up about this. – Brigand Feb 01 '15 at 09:39
  • 2
    Using a class is faster by a couple orders of magnitude. It's good to know. – Jason Rice Mar 03 '15 at 21:13
  • 1
    Could just use conditional class names with: https://github.com/JedWatson/classnames – backdesk Nov 30 '15 at 16:20
9

A simple method to show/hide elements in React using Hooks

const [showText, setShowText] = useState(false);

Now, let's add some logic to our render method:

{showText && <div>This text will show!</div>}

And

onClick={() => setShowText(!showText)}

Good job.

superup
  • 1,765
  • 13
  • 12
8

I was able to use css property "hidden". Don't know about possible drawbacks.

export default function App() {
    const [hidden, setHidden] = useState(false);
    return (
      <div>
        <button onClick={() => setHidden(!hidden)}>HIDE</button>
        <div hidden={hidden}>hidden component</div>
      </div>
    );
  }
farynaa
  • 330
  • 3
  • 7
7

Best practice is below according to the documentation:

{this.state.showFooter && <Footer />}

Render the element only when the state is valid.

ravibagul91
  • 20,072
  • 5
  • 36
  • 59
Dynamic
  • 1,553
  • 2
  • 19
  • 25
  • 1
    This answer was already [given](https://stackoverflow.com/a/39401319/1269037) a year earlier, so it's OK to delete it now. – Dan Dascalescu Oct 25 '19 at 08:56
7

Simple hide/show example with React Hooks: (srry about no fiddle)

const Example = () => {

  const [show, setShow] = useState(false);

  return (
    <div>
      <p>Show state: {show}</p>
      {show ? (
        <p>You can see me!</p>
      ) : null}
      <button onClick={() => setShow(!show)}>
    </div>
  );

};

export default Example;
StefanBob
  • 4,857
  • 2
  • 32
  • 38
5

I start with this statement from the React team:

In React, you can create distinct components that encapsulate behaviour you need. Then, you can render only some of them, depending on the state of your application.

Conditional rendering in React works the same way conditions work in JavaScript. Use JavaScript operators like if or the conditional operator to create elements representing the current state, and let React update the UI to match them.

You basically need to show the component when the button gets clicked, you can do it two ways, using pure React or using CSS, using pure React way, you can do something like below code in your case, so in the first run, results are not showing as hideResults is true, but by clicking on the button, state gonna change and hideResults is false and the component get rendered again with the new value conditions, this is very common use of changing component view in React...

var Search = React.createClass({
  getInitialState: function() {
    return { hideResults: true };
  },

  handleClick: function() {
    this.setState({ hideResults: false });
  },

  render: function() {
    return (
      <div>
        <input type="submit" value="Search" onClick={this.handleClick} />
        { !this.state.hideResults && <Results /> }
      </div> );
  }

});

var Results = React.createClass({
  render: function() {
    return (
    <div id="results" className="search-results">
      Some Results
    </div>);
   }
});

ReactDOM.render(<Search />, document.body);

If you want to do further study in conditional rendering in React, have a look here.

Alireza
  • 100,211
  • 27
  • 269
  • 172
5
   class FormPage extends React.Component{
      constructor(props){
           super(props);
           this.state = {
             hidediv: false
           }
      }

     handleClick = (){
       this.setState({
          hidediv: true
        });
      }

      render(){
        return(
        <div>
          <div className="date-range" hidden = {this.state.hidediv}>
               <input type="submit" value="Search" onClick={this.handleClick} />
          </div>
          <div id="results" className="search-results" hidden = {!this.state.hidediv}>
                        Some Results
           </div>
        </div>
        );
      }
  }
Akanksha gore
  • 558
  • 1
  • 8
  • 7
5
class Toggle extends React.Component {
  state = {
    show: true,
  }

  render() {
    const {show} = this.state;
    return (
      <div>
        <button onClick={()=> this.setState({show: !show })}>
          toggle: {show ? 'show' : 'hide'}
        </button>    
        {show && <div>Hi there</div>}
      </div>
     );
  }
}
sgr
  • 81
  • 1
  • 2
  • 8
3

If you would like to see how to TOGGLE the display of a component checkout this fiddle.

http://jsfiddle.net/mnoster/kb3gN/16387/

var Search = React.createClass({
    getInitialState: function() {
        return { 
            shouldHide:false
        };
    },
    onClick: function() {
        console.log("onclick");
        if(!this.state.shouldHide){
            this.setState({
                shouldHide: true 
            })
        }else{
                    this.setState({
                shouldHide: false 
            })
        }
    },
render: function() {
    return (
      <div>
        <button onClick={this.onClick}>click me</button>
        <p className={this.state.shouldHide ? 'hidden' : ''} >yoyoyoyoyo</p>
      </div>
    );
}
});

ReactDOM.render( <Search /> , document.getElementById('container'));
Nicholas Porter
  • 2,588
  • 2
  • 23
  • 37
3

Use ref and manipulate CSS

One way could be to use React's ref and manipulate CSS class using the browser's API. Its benefit is to avoid rerendering in React if the sole purpose is to hide/show some DOM element on the click of a button.

// Parent.jsx
import React, { Component } from 'react'

export default class Parent extends Component {
    constructor () {    
        this.childContainer = React.createRef()
    }

    toggleChild = () => {
        this.childContainer.current.classList.toggle('hidden')
    }

    render () {
        return (
            ...

            <button onClick={this.toggleChild}>Toggle Child</button>
            <div ref={this.childContainer}>
                <SomeChildComponent/>
            </div>

            ...
        );
    }
}


// styles.css
.hidden {
    display: none;
}

PS Correct me if I am wrong. :)

UtkarshPramodGupta
  • 7,486
  • 7
  • 30
  • 54
  • Created codesandbox.io example, here: https://utgzx.csb.app/, code is at https://codesandbox.io/embed/react-show-hide-with-css-utgzx – PatS Aug 21 '19 at 16:57
  • While it would definitely work, it's considered an anti-pattern to manipulate the DOM unless you don't have the choice, e.g. when integrating an incompatible 3rd-party library, like an old jQuery widget, etc. – Emile Bergeron Jul 05 '21 at 21:34
  • 1
    You're absolutely right @EmileBergeron. It's one of the unoptimized way to do it when you are not willing to introduce State in the component. It wrote it answer 2yrs back when I was still a newbie in React. – UtkarshPramodGupta Jul 07 '21 at 05:24
2

In some cases higher order component might be useful:

Create higher order component:

export var HidableComponent = (ComposedComponent) => class extends React.Component {
    render() {
        if ((this.props.shouldHide!=null && this.props.shouldHide()) || this.props.hidden)
            return null;
        return <ComposedComponent {...this.props}  />;
    }
};

Extend your own component:

export const MyComp= HidableComponent(MyCompBasic);

Then you can use it like this:

<MyComp hidden={true} ... />
<MyComp shouldHide={this.props.useSomeFunctionHere} ... />

This reduces a bit boilerplate and enforces sticking to naming conventions, however please be aware of that MyComp will still be instantiated - the way to omit is was mentioned earlier:

{ !hidden && <MyComp ... /> }

vinga
  • 1,912
  • 20
  • 33
2
//use ternary condition

{ this.state.yourState ? <MyComponent /> : null } 

{ this.state.yourState && <MyComponent /> }

{ this.state.yourState == 'string' ? <MyComponent /> : ''}

{ this.state.yourState == 'string' && <MyComponent /> }

//Normal condition

if(this.state.yourState){
 return <MyComponent />
}else{
  return null;
}


<button onClick={()=>this.setState({yourState: !this.props.yourState}>Toggle View</button>
Naved Khan
  • 1,699
  • 16
  • 13
1

If you use bootstrap 4, you can hide element that way

className={this.state.hideElement ? "invisible" : "visible"}
ThomasP1988
  • 4,597
  • 3
  • 30
  • 36
1

Use rc-if-else module

npm install --save rc-if-else
import React from 'react';
import { If } from 'rc-if-else';

class App extends React.Component {
    render() {
        return (
            <If condition={this.props.showResult}>
                Some Results
            </If>
        );
    }
}
qinyuanbin
  • 11
  • 5
1

Use this lean and short syntax:

{ this.state.show && <MyCustomComponent /> }
Zayn
  • 741
  • 1
  • 5
  • 22
  • 1
    Maybe you could expand on your lean & short syntax to explain how it works. Oh wait, that was done in an answer [3 years earlier](https://stackoverflow.com/a/39401319/1269037). What does your answer bring to the table again? – Dan Dascalescu Oct 25 '19 at 09:02
1

Here comes the simple, effective and best solution with a Classless React Component for show/hide the elements. Use of React-Hooks which is available in the latest create-react-app project that uses React 16

import React, {useState} from 'react';
function RenderPara(){
const [showDetail,setShowDetail] = useState(false);

const handleToggle = () => setShowDetail(!showDetail);

return (
<React.Fragment>
    <h3>
        Hiding some stuffs 
    </h3>
    <button onClick={handleToggle}>Toggle View</button>
   {showDetail && <p>
        There are lot of other stuffs too
    </p>}
</React.Fragment>)

}  
export default RenderPara;

Happy Coding :)

1

Just figure out a new and magic way with using(useReducer) for functional components

const [state, handleChangeState] = useReducer((state) => !state, false); change state

ahmed mersal
  • 167
  • 2
  • 3
0

This can also be achieved like this (very easy way)

 class app extends Component {
   state = {
     show: false
   };
 toggle= () => {
   var res = this.state.show;
   this.setState({ show: !res });
 };
render() {
  return(
   <button onClick={ this.toggle }> Toggle </button>
  {
    this.state.show ? (<div> HELLO </div>) : null
  }
   );
     }
Mohammad Basit
  • 971
  • 6
  • 18
  • 1
    Please read about setting "state based on the previous state" at https://reactjs.org/docs/react-component.html#setstate. Also, would be nice to fix the indentation at the end. – Dan Dascalescu Oct 25 '19 at 09:07
0

this example shows how you can switch between components by using a toggle which switches after every 1sec

import React ,{Fragment,Component} from "react";
import ReactDOM from "react-dom";

import "./styles.css";

const Component1 = () =>(
  <div>
    <img 
src="https://i.pinimg.com/originals/58/df/1d/58df1d8bf372ade04781b8d4b2549ee6.jpg" />
   </div>
)

const Component2 = () => {
  return (
    <div>
       <img 
src="http://www.chinabuddhismencyclopedia.com/en/images/thumb/2/2e/12ccse.jpg/250px- 
12ccse.jpg" />
  </div>
   )

 }

 class App extends Component {
   constructor(props) {
     super(props);
    this.state = { 
      toggleFlag:false
     }
   }
   timer=()=> {
    this.setState({toggleFlag:!this.state.toggleFlag})
  }
  componentDidMount() {
    setInterval(this.timer, 1000);
   }
  render(){
     let { toggleFlag} = this.state
    return (
      <Fragment>
        {toggleFlag ? <Component1 /> : <Component2 />}
       </Fragment>
    )
  }
}


const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Snivio
  • 1,741
  • 1
  • 17
  • 25
0

The application of states and effects has and must be encapsulated in the same component, for this reason, there is nothing better than creating a custom component as a hook to solve in this case whether to make particular blocks or elements visible or invisible.

// hooks/useOnScreen.js

import { useState, useEffect } from "react"

const useOnScreen = (ref, rootMargin = "0px") => {

  const [isVisible, setIsVisible] = useState(false)

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        setIsVisible(entry.isIntersecting)
      },
      {
        rootMargin
      }
    );

    const currentElement = ref?.current

    if (currentElement) {
      observer.observe(currentElement)
    }

    return () => {
      observer.unobserve(currentElement)
    }
  }, [])

  return isVisible
}

export default useOnScreen

Then the custom hook is embedded inside the component

import React, { useRef } from "react";
import useOnScreen from "hooks/useOnScreen";

const MyPage = () => {

  const ref = useRef(null)

  const isVisible = useOnScreen(ref)

  const onClick = () => {
    console.log("isVisible", isVisible)
  }
  
  return (
    <div ref={ref}>
      <p isVisible={isVisible}>
        Something is visible
      </p>
      <a
        href="#"
        onClick={(e) => {
          e.preventDefault();
          onClick(onClick)
        }}
      >
        Review
      </a>
    </div>
  )
}

export default MyPage

The ref variable, controlled by the useRef hook, allows us to capture the location in the DOM of the block that we want to control, then the isVisible variable, controlled by the useOnScreen hook, allows us to make the inside the block I signal by the useRef hook. I believe that this implementation of the useState, useEfect, and useRef hooks allows you to avoid component rendering by separating them using custom hooks.

Hoping that this knowledge will be of use to you.

Jorge Pirela
  • 129
  • 1
  • 6
0

It is very simple to hide and show the elements in react.

There are multiple ways but I will show you two.

Way 1:

const [isVisible, setVisible] = useState(false)

let onHideShowClick = () =>{
    setVisible(!isVisible)
}

return (<div> 
        <Button onClick={onHideShowClick} >Hide/Show</Button>
         {(isVisible) ? <p>Hello World</p> : ""}
</div>)

Way 2:

const [isVisible, setVisible] = useState(false)

let onHideShowClick = () =>{
    setVisible(!isVisible)
}

return (<div> 
        <Button onClick={onHideShowClick} >Hide/Show</Button>
        <p style={{display: (isVisible) ? 'block' : 'none'}}>Hello World</p>
</div>)

It is just working like if and else.

In Way one, it will remove and re-render elements in Dom. In the Second way you are just displaying elements as false or true.

Thank you.

0

You've to do the small change in the code for continuously hiding and showing

const onClick = () => {setShowResults(!showResults}

Problem will be solved

const Search = () => {
  const [showResults, setShowResults] = React.useState(false)
  const onClick = () => setShowResults(true)
  const onClick = () => {setShowResults(!showResults}
  return (
    <div>
      <input type="submit" value="Search" onClick={onClick} />
      { showResults ? <Results /> : null }
    </div>
  )
}
const Results = () => (
  <div id="results" className="search-results">
    Some Results
  </div>
)
ReactDOM.render(<Search />, document.querySelector("#container"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>
```
Ihtisham Khattak
  • 170
  • 1
  • 2
  • 11
-1
// Try this way

class App extends Component{

  state = {
     isActive:false
  }

  showHandler = ()=>{
      this.setState({
          isActive: true
      })
  }

  hideHandler = () =>{
      this.setState({
          isActive: false
      })
  }

   render(){
       return(
           <div>
           {this.state.isActive ? <h1>Hello React jS</h1> : null }
             <button onClick={this.showHandler}>Show</button>
             <button onClick={this.hideHandler}>Hide</button>
           </div>
       )
   }
}
Force Bolt
  • 1,117
  • 9
  • 9
-2
var Search= React.createClass({
 getInitialState: () => { showResults: false },
 onClick: () => this.setState({ showResults: true }),
 render: function () {
   const { showResults } = this.state;
   return (
     <div className="date-range">
       <input type="submit" value="Search" onClick={this.handleClick} />
       {showResults && <Results />}
     </div>
   );
 }
});

var Results = React.createClass({
    render: function () {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

React.renderComponent(<Search /> , document.body);
-2

var Search = React.createClass({
    getInitialState: function() {
        return { showResults: false };
    },
    onClick: function() {
        this.setState({ showResults: true });
    },
    render: function() {
        return (
            <div>
                <input type="checkbox" value="Search" onClick={this.onClick} />
                { this.state.showResults ? <Results /> : null }
            </div>
        );
    }
});

var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className="search-results">
                <input type="text" />
            </div>
        );
    }
});

ReactDOM.render( <Search /> , document.getElementById('container'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.min.js"></script>

<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>
Venka
  • 1
  • 4
    While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. – xiawi Sep 19 '19 at 08:18
  • What @xiawi said. Also, please use `const` instead of `var` when you declare constants. – Dan Dascalescu Oct 25 '19 at 09:09
-3
class App extends React.Component {
  state = {
    show: true
  };

  showhide = () => {
    this.setState({ show: !this.state.show });
  };

  render() {
    return (
      <div className="App">
        {this.state.show && 
          <img src={logo} className="App-logo" alt="logo" />
        }
        <a onClick={this.showhide}>Show Hide</a>
      </div>
    );
  }
}
  • 1
    Can you please add explanation for better understanding? Thanks! – Shanteshwar Inde Sep 11 '19 at 11:22
  • 1
    @ShanteshwarInde: this duplicates the same idea from a [previous answer](https://stackoverflow.com/a/54275578/1269037), including incorrect usage of setState depending on the current state. See https://reactjs.org/docs/react-component.html#setstate: "If you need to set the state based on the previous state, read about the updater argument". – Dan Dascalescu Oct 25 '19 at 09:08