React js - Show or hide a div

Viewed 3484

I am trying to show or hide a div in Reactjs using the state value in the CSS style option - display and I am using functions with hooks. I have a button and below the button a div. When i click the button i either want to hide or show the contents in the div based on whether it is currently shown or hidden.

This is the basic test code I have

import React, { useState } from "react";

function hide() {
  return (
    <div>
      <Mycomp />
    </div>
  );
}

function Mycomp() {
  const [dp, setDp] = useState("none");

  return (
    <form>
      <button
        onClick={() => {
          setDp("block");
        }}
      >
        Test
      </button>
      <div style={{ display: dp }}>Test</div>
    </form>
  );
}

export default hide;

I then use this hide component in my App.js file. When I click the button the new state is assigned but then the page re-renders and the initial state is loaded again almost immediately. How can I go by ensuring the new state is kept? Eventually I will create a function where if the div display or not based on the previous state.

3 Answers

The issue is that the button is inside a <form>. So any click on that button will submit the form and refresh the page.

Can I make a <button> not submit a form?

You need to add a type="button" to your <button>

import React, { useState } from "react";

function Hide() {
  return (
    <div>
      <Mycomp />
    </div>
  );
}

function Mycomp() {
  const [dp, setDp] = useState(false);

  return (
    <form>
      <button
        type="button"
        onClick={() => setDp(!dp)}
      >
        Test
      </button>
      {dp && <div>Test</div>}
    </form>
  );
}

export default Hide;

Your code should be something like this, instead of using block and none as style we can use conditional JSX (which is more ideal approach) -:

function Mycomp(){
    const[dp, toggleDp] = useState(false);

    return(
        <form>
            <button onClick={()=>{toggleDp(!dp)}}>Test</button>
            {dp && <div>Test</div>}
        </form>
    )
}

export default hide

A better implementation would be to have your state variable TRUE/FALSE value and based on it display the element using a conditional rendering, note e.preventDefault in the button handler to stop the refresh/redirect, here is a working snippet, also a codesandbox:

const { useState, useEffect } = React;

function App() {
  return (
    <div>
      <Mycomp />
    </div>
  );
}

function Mycomp() {
  const [dp, setDp] = useState(true);

  return (
    <form>
      <button
        onClick={(e) => {
          e.preventDefault();
          setDp(!dp);
        }}
      >
        Test
      </button>
      {dp && <div>Test</div>}
    </form>
  );
}

ReactDOM.render(<App />, document.getElementById("react-root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>

Related