It's hard to say without seeing the whole component's view, but the problem may lie in the structure of your HTML code.
If the button that calls the hide method is inside of the div that shows it, event propagation is likely to be the source of the problem. Let's assume that your view has a structure like this:
<div className="item" onClick={showDetails}>
{show ? (
<div className="details-container">
<button onClick={hideDetails}>Hide</button>
</div>
) : null}
</div>
There's nothing wrong with the way you're calling setState per se, but when you click on the button two things happen:
The hideDetails method is called when the button is clicked, so show is set to false.
The click event is propagated to the parent elements and, since the button is inside of the div, this causes the showDetails to run again and show is set back to true.
This last step explains why your element keeps showing even after the button has been clicked. The solution for this is to stop event propagation on the hideDetails method, like this:
function hideDetails(e) {
e.stopPropagation();
setShow(false);
}
Stopping propagation will ensure that only the click event handler of the button runs, so showDetails will no longer be executed when the button is clicked.
The full working example is listed below:
const App = () => {
const [show, setShow] = React.useState(false);
const showDetails = () => {
setShow(true);
};
const hideDetails = (e) => {
e.stopPropagation();
setShow(false);
};
return (
<div className="item" onClick={showDetails}>
<b>Item</b>
{show ? (
<div className="details-container">
<p>Details</p>
<button onClick={hideDetails}>Hide</button>
</div>
) : null}
</div>
);
};
ReactDOM.render(
<App />,
document.getElementById("react")
);
.item {
padding: 1em;
background: #CCCCCC;
border: black solid 1px;
}
.details-container {
padding: 1em;
background: #EEEEEE;
border: black solid 1px;
}
p {
margin: 0 0 .5em 0;
}
<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"></div>