On React, I attempted making a feature to let user can see active feedback on screen by changing its icon when they click it.
How can I let it change to another icon (e.g. from Box to BoxChecked) once I click it?
note: I know this code line is the problem...(sob)
<img src={click} alt="icon" onClick={handleClick} />
App.jsx
import React, { useState } from 'react'
import './App.css'
import { GrCheckbox as Box } from 'react-icons/gr'
import { GrCheckboxSelected as BoxChecked } from 'react-icons/gr'
export default function App() {
const [icon, setIcon] = useState(false);
const [click, setClick] = useState(Box);
function handleClick() {
setIcon(!icon);
icon ? setClick(Box) : setClick(BoxChecked);
}
return (
<div className="App">
<img src={click} alt="icon" onClick={handleClick} />
<p>Clicked {click} times</p>
</div>
);
}
CodePudding user response:
useState
is async so you don't have the value of icon immediately after the execution of setIcon
in your handler.
You need to put the setClick
call in a useEffect
hook:
React.useEffect(() => {
icon ? setClick(Box) : setClick(BoxChecked);
}, [icon]);
function handleClick() {
setIcon(!icon);
}
This effect will be executed when icon changes because it is added to the useEffect
's dependency array. Have a look at the docs for more info:
https://reactjs.org/docs/hooks-effect.html
CodePudding user response:
Storing a component in state is not recommended. Use condition to set src
.
<img src={icon ? Box : BoxChecked} alt="icon" onClick={handleClick} />
Change handler to this
function handleClick() {
setIcon(prevIcon => !prevIcon);
}
or better
const handleClick = useCallback(() => {
setIcon(prevIcon => !prevIcon);
}, []);