Reputation: 569
Is it not possible to update classNames on rerender?
const [selected, setSelectedState] = useState(true);
let className = "none";
useEffect(() => {
className = "appointment-item " + (selected ? "selected" : "");
console.log(className );
}, [selected] );
return (
<div className={`${className}`} onClick={()=>setSelectedState(!selected)}>{Math.random()}</div>
);
className
in the console shows correctly, but when the div rerenders (which i see because the random number updates), the className stays as "none". I am also confused because I thought useEffect runs immediately as well.. so it should never be "none" in the first place becuase it should get overwritten right away?
Upvotes: 3
Views: 7867
Reputation: 14844
You can achieve that using a useState
hook for the className
variable if you want to use useEffect
:
const [selected, setSelectedState] = useState(true);
const [className , setClassName] = useState("none");
useEffect(() => {
setClassName("appointment-item " + (selected ? "selected" : ""))
console.log(className );
}, [selected] );
return (
<div className={className} onClick={()=>setSelectedState(!selected)}>{Math.random()}</div>
);
But I highly recommend @MarkoCen response.
Upvotes: 0
Reputation: 31
You don't need to have an useEffect for this.
all you need,
const [selected, setSelectedState] = useState(true);
let clsName = 'appointment-item ' + (selected ? 'selected' : '');
return(
<div className={`${clsName}`} onClick={() => setSelectedState(!selected)}>
{Math.random()}
</div>
)
Upvotes: 1
Reputation: 1826
To add more details on @MarkoCen answers (that is right), there are few things to know when working with hooks:
useEffect
runs after each render.
On each render, the component re-executes from beginning, after the hooks definition. Given your code (I added comments to identity each cycle)
const [selected, setSelectedState] = useState(true); // 0
let className = "none"; // 1
useEffect(() => {
// 3
className = "appointment-item " + (selected ? "selected" : "");
console.log(className );
}, [selected] );
// 2
return (
<div className={`${className}`} onClick={()=>setSelectedState(!selected)}>{Math.random()}</div>
);
Here are the cycles in order:
First render:
0: useState
1: className = none
2: render with className = none
3: useEffect
Re-renders:
1: className = none
2: re-render with className = none
3: useEffect
As you can see, each render set className
to "none" each time, so you will never have what you expect.
Upvotes: 6
Reputation: 2324
No need useEffect
since selected
already defined as a state, and you can compute the class name from selected
const [selected, setSelectedState] = useState(true);
const className = "appointment-item " + (selected ? "selected" : "");
return (
<div className={className} />
)
Upvotes: 3