skip to Main Content

I have a task that is simple (one line) in plain HTML/CSS/JS, but I can’t find a simple and working method in React.

I have a parent div, and it has two children. The second child is the meaningful content. The first child is a "hide" button, that, when clicked, hides the parent div (including, of course, both child divs).

function SecondPage({ thisData }) {

    function hidePage(thisID) {
        let thisElement = document.getElementById(thisID)
        thisElement.style.display='none';
    }

    return ( <>
        <div className="page" id="InfoPage1">
            <div className="hidePageButton" onClick={hidePage("InfoPage1")}>
                ✖
            </div>
            <div className="pageContent"> 
                Some text and stuff
            </div>
        </div>

        <div className="page" id="InfoPage2">
            <div className="hidePageButton" onClick={hidePage("InfoPage2")}>
                ✖
            </div>
            <div className="pageContent"> 
                Some text and stuff
            </div>
        </div>
    </> );
}
export default SecondPage;

In fact, there is an even easier/simpler way using onClick={hidePage(this)} and function hidePage(el) {el.parentNode.style.display='none' }

But these methods don’t work in React. I’ve seen some proposed solutions for React that supposedly do what I want, but they are complicated. They propose defining classes with embedded functions and all kinds of seemingly extra baggage to do this simple task.

I’ve also read hints that being able to get elements by IDs and getting parents is not in line with React’s philosophy. But I don’t care about that. I don’t need the best way according to React gospel, or the most modular, or the safest, or anything like that.

What is the simplest possible way to get a div button to hide its parent div (or make other style changes) on click in React (jsx).


I’ve edited the question after receiving a few great answers because they couldn’t obviously handle something closer to my real case: multiple instances per HTML block. One of the points of passing the elementID to the hide function is to tell the hide function which div element to hide (in my case, its immediate parent). I don’t see how to support multiple instances per page with the current proposed solutions.

3

Answers


    • You need a ref of parent div
    • An onClick handler to Set parent div display to none
    import { useCallback, useRef } from 'react';
    import './App.css';
    
    function App() {
      const pageRef = useRef(null);
      const hidePage = useCallback(() => {
        pageRef.current.style.display = 'none';
      }, [pageRef.current]);
    
      return (
        <div className="page" id="InfoPage" ref={pageRef}>
          <div className="hidePageButton" onClick={hidePage}>
            ✖
          </div>
          <div className="pageContent">Some text and stuff</div>
        </div>
      );
    }
    
    export default App;
    

    Working sample: https://stackblitz.com/edit/vitejs-vite-amkkzf?file=src%2FApp.jsx

    Login or Signup to reply.
  1. More simple way IMO without using ref, just defining parent style

    import { useState } from "react";
    
    export default function App() {
      const [visible, setVisible] = useState(true);
    
      function hidePage() {
        setVisible((prev) => !prev);
      }
    
      return (
        <div className="App">
          <h1>title</h1>
          <div style={{ display: visible ? "block" : "none" }}>
            <button onClick={hidePage}>hide</button>
            <div>Some text</div>
          </div>
        </div>
      );
    }
    

    Example

    Login or Signup to reply.
  2. What is the simplest possible way to get a div button to hide its parent div

    For styling; Use a state that will apply a CSS class. Then add any styling (eg: display: none) to the class you’re adding.

    • getElementById should be avoided in React when possible
    • A ref is overcomplicating things
    • (You could use inline styling instead of a class, but this keeps your code readable)

    Minimal working example:

    const { useState } = React;
    
    const Example = () => {
    
        const [hide, setHide] = useState(false);
    
        return (
            <div>
                <h1>{'Example'}</h1>
                <div className={hide ? 'hide' : ''}>
                    <em>I'm the div!</em>
                    <button onClick={() => setHide(true)}>
                        Press me to hide the div
                    </button>
                </div>
            </div>
        )
    }
    ReactDOM.render(<Example />, document.getElementById("react"));
    .hide {
        display: none;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>

    If you wish to prevent the content from rendering, you could wrap the div in a conditional render:

    const { useState } = React;
    
    const Example = () => {
    
        const [show, setShow] = useState(true);
    
        return (
            <div>
                <h1>{'Example'}</h1>
                {
                    (show) && (
                        <div>
                            <em>I'm the div!</em>
                            <button onClick={() => setShow(false)}>
                                Press me to hide the div
                            </button>
                        </div>
                    )
                }
            </div>
        )
    }
    ReactDOM.render(<Example />, document.getElementById("react"));
    .hide {
        display: none;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search