I have this code that uses useState to make a form appear or disapear when clicking a button
const [searchClick, setSearchClick] = useState("hidden")
// Button when clicked the form appears or disappears
<label onClick={() => setSearchClick(prevState => prevState ==='hidden' ? 'flex' : 'hidden') } className="btn-xs btn-ghost rounded-full w-fit h-fit swap swap-rotate" >
<input type="checkbox" />
<Search className="swap-off relative right-1" width="22px" height="22px" fill='#8DD0BA' />
<svg className="swap-on fill-current" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 512 512"><polygon points="400 145.49 366.51 112 256 222.51 145.49 112 112 145.49 222.51 256 112 366.51 145.49 400 256 289.49 366.51 400 400 366.51 289.49 256 400 145.49"/></svg>
</label>
<form className={`${searchClick} my-6 justify-center`}>
<input type="text" placeholder="Search" className="input input-bordered max-w-lg bg-white text-black" />
<button className="btn w-18 rounded-r-none"><Search /></button>
</form>
when I'm putting the onclick function in the label tag it causing two renders and it's not working well but when I'm putting it in the input tag it's working well
CodePudding user response:
The problem is not in React rendering, but in handling label
clicks. Your handling function is first triggered from label
or its children svg
or polygon
(causing render) and then from input
(another render). It can be logged and debugged like this with event.target
:
function YourComponent() {
const [searchClick, setSearchClick] = useState("hidden");
const onClickFnc = (event) => {
console.log("onClick called", event.target);
setSearchClick((prevState) => (prevState === "hidden" ? "flex" : "hidden"));
};
console.log("rendering component");
return (
<div>
<label
onClick={onClickFnc}
className="btn-xs btn-ghost rounded-full w-fit h-fit swap swap-rotate"
>
<input type="checkbox" />
<svg
className="swap-on fill-current"
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 512 512"
>
<polygon points="400 145.49 366.51 112 256 222.51 145.49 112 112 145.49 222.51 256 112 366.51 145.49 400 256 289.49 366.51 400 400 366.51 289.49 256 400 145.49" />
</svg>
</label>
<div>Current state: {searchClick}</div>
</div>
);
}
It can be solved by adding handler on input
and some event.stopPropagation()
, nice example here: https://stackoverflow.com/a/38958110/5940854