here is my code, when I click on an Icon(4 icons) they all show text, my 4 icons have the same code structure, I don't know maybe I should add some id ? or do you have a more good choice? can you help me, please :)
const [showText, setShowText] = useState(false)
const toggleText = () => setShowText((text) => !text)
<div className="inline-flex justify-center items-center">
<Button className=" border-none bg-white" onClick={toggleText}>
<IconUsers size={30} stroke={1} />
</Button>
{showText && (
<Text className=" inline-flex justify-center items-center align-text-top ">
devenir member
</Text>
)}
</div>
<div className="inline-flex justify-center items-center">
<Button className=" border-none bg-white" onClick={toggleText}>
<IconHeart size={30} stroke={1} />
</Button>
{showText && (
<Text className="flex justify-center items-center align-text-top ">
favorites
</Text>
)}
</div>
<div className="inline-flex justify-center items-center">
<Button className=" border-none bg-white" onClick={toggleText}>
<IconMail size={30} stroke={1} />
</Button>
{showText && (
<Text className="flex justify-center items-center align-text-top ">
notification
</Text>
)}
</div>
<div className="inline-flex justify-center items-center">
<Button className=" border-none bg-white" onClick={toggleText}>
<IconMathSymbols size={30} stroke={1} />
</Button>
{showText && (
<Text className="flex justify-center items-center align-text-top ">
total
</Text>
)}
</div>
how can I fix it? like click on 1 icon and will only show his own text open 1
CodePudding user response:
All of your button/text is using the same set of function setter and state, so it will behave the same way when you click on one.
The easiest way is just to extract them into a component like this
//TextWithButton.jsx (multiple codes r removed)
const [showText, setShowText] = useState(false)
const toggleText = () => setShowText((text) => !text)
<div className="inline-flex justify-center items-center">
<Button className=" border-none bg-white" onClick={toggleText}>
<IconUsers size={30} stroke={1} />
</Button>
{showText && (
<Text className=" inline-flex justify-center items-center align-text-top ">
devenir member
</Text>
)}
</div>
// parent.tsx (multiple codes r removed)
<TextWithButton />
<TextWithButton />
<TextWithButton />
<TextWithButton />
However, I feel like you are missing an understanding of the concept of components in React. I would recommend you to read this article through :)
CodePudding user response:
Hi you will need to store more information in state. Instead of boolean true false you should store something that can be used as ID, unique to all buttons.
For example
const [selected, setSelected] = useState()
And then toggleText could become toggleSelected and needs to take the id of the element that was selected as an argument.
const toggleText = (id) => setSelected(id)
Then in the code for one of the buttons it becomes
//assuming we call this one with id favorite
<div className="inline-flex justify-center items-center">
<Button className=" border-none bg-white" onClick={()=>toggleText("favorite")}>
<IconHeart size={30} stroke={1} />
</Button>
{selected==="favorite" && (
<Text className="flex justify-center items-center align-text-top">
favorites
</Text>
)}
</div>
You can then make similar changes for the rest of the buttons giving whatever ids you want. If using typescript you can ensure the state is correct assigned an expected value with something like
type Option = "favorite" | "membership" | "total" | "notification"
...
const [selected,setSelected] = useState<Option>()
...
const toggleText = (id:Option) => setSelected(id)
This will work and keep the structure as it is. Then eventually what you would probably want is to create a component for that and remove some repetition for the logic.
Best