4

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.

ROOT
  • 11,363
  • 5
  • 30
  • 45
Jason Samuels
  • 65
  • 2
  • 5

3 Answers3

3

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;
klugjo
  • 19,422
  • 8
  • 57
  • 75
  • On runtime this shows a button, click the button and it shows the text, but clicking the button again does not hide the text. Also not sure why we're importing ./styles.css here...? – Dieter Jun 06 '22 at 18:44
  • You are right, not sure what I was thinking when I wrote this. Updated my answer. – klugjo Jun 07 '22 at 06:10
1

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
Abhisar Tripathi
  • 1,569
  • 10
  • 21
1

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>
ROOT
  • 11,363
  • 5
  • 30
  • 45