I'm trying to implement a form with email and communication channels and want to update the form and then save it. While updating I'm facing the problem to toggle the button/icon. Please find the code below:
const [checked, setChecked] = useState(false);
const toggleChecked = (e) => {
setChecked((checked) => {
return !checked;
});
};
const form = useForm({
initialValues: {
email: "",
communication: [
{
email: {
email: "",
notification: true,
},
whatsapp: {
notification: false,
},
},
],
},
My table content is like the below:
<form>
<Table>
<thead>
<tr>
<th>Communication channel</th>
<th>Notifications</th>
</tr>
</thead>
<tbody>
<tr>
<td>Email</td>
<td>
{checked? (
<CheckCircleIcon
className="h-6 w-6 text-green-500"
onClick={() => toggleChecked()}
/>
) : (
<XCircleIcon
className="h-6 w-6 text-red-500"
onClick={() => toggleChecked()}
/>
)}
</td>
</tr>
<tr>
<td>Whatsapp</td>
<td>
{checked? (
<CheckCircleIcon
className="h-6 w-6 text-green-500"
onClick={() => toggleChecked()}
/>
) : (
<XCircleIcon
className="h-6 w-6 text-red-500"
onClick={() => toggleChecked()}
/>
)}
</td>
</tr>
</tbody>
</Table>
</form>
What I want :
The green tick and Red cross are representing the boolean of the corresponding channel. Then should be clickable and change to the opposite symbol. In addition, user documents stored in memory should also change.
What problem I'm having now :
If I click the first icon for email the second icon for whatsapp is also changing I want to click the individual elements to change their state. What can I do? Please suggest.
use two states like: emailChecked
and whatsappChecked
with corresponding toggle handlers:
const toggleEmailChecked = () => {
setEmailChecked((checked) => {
return !checked;
});
};
const toggleWhatsappChecked = () => {
setWhatsappChecked((checked) => {
return !checked;
});
};
First of all you will need to maintain checked state of each email channel, like this
const [emailChecked, setEmailChecked] = useState(false);
const [whatsappChecked, setWhatsappChecked] = useState(false);
now you will need to have two toggle function one for email and one for whatsapp.
//for email
const toggleEmailChecked = (e) => {
setEmailChecked(!emailChecked);
};
///for whatsapp
const toggleWhatsAppChecked = (e) => {
setWhatsappChecked(!whatsappChecked);
};
now use it like this way
<form>
<Table>
<thead>
<tr>
<th>Communication channel</th>
<th>Notifications</th>
</tr>
</thead>
<tbody>
<tr>
<td>Email</td>
<td>
{emailChecked? (
<CheckCircleIcon
className="h-6 w-6 text-green-500"
onClick={() => toggleEmailChecked()}
/>
) : (
<XCircleIcon
className="h-6 w-6 text-red-500"
onClick={() => toggleEmailChecked()}
/>
)}
</td>
</tr>
<tr>
<td>Whatsapp</td>
<td>
{whatsappChecked? (
<CheckCircleIcon
className="h-6 w-6 text-green-500"
onClick={() => toggleWhatsAppChecked()}
/>
) : (
<XCircleIcon
className="h-6 w-6 text-red-500"
onClick={() => toggleWhatsAppChecked()}
/>
)}
</td>
</tr>
</tbody>
</Table>
</form>
hope this will help.
First solution - 2 separate states
One solution for your problem would be to keep track of two separate states, for example:
const [whatsappChecked, setWhatsappChecked] = useState(false);
const [emailChecked, setEmailChecked] = useState(false);
Then, each button would call its own setter, like this:
<CheckCircleIcon
className="h-6 w-6 text-green-500"
onClick={() => setWhatsappChecked(!whatsappChecked)}
/>
and
<CheckCircleIcon
className="h-6 w-6 text-green-500"
onClick={() => setEmailChecked(!emailChecked)}
/>
2nd solution - extract the component and keep the state in the component
Your second solution would be to extract the state and the icons as a separate component. In that component you would keep track of whether the user toggled the individual button, the same way you do now, with just one state
const [isChecked, setIsChecked] = useState(false);
But you would call this component twice, once for each button. Each component would keep its own separate state and not be aware of the state of the other button.
The component would look something like this:
function ToggleButton() {
const [isChecked, setIsChecked] = useState(false);
return isChecked? <CheckCircleIcon
className="h-6 w-6 text-green-500"
onClick={() => setIsChecked(!isChecked)}
/>
: <XCircleIcon
className="h-6 w-6 text-red-500"
onClick={() => setIsChecked(!isChecked)}
/>
}
And you would call it in your form as
<tr>
<td>Email</td>
<td><ToggleButton /></td>
</tr>
<tr>
<td>Whatsapp</td>
<td><ToggleButton /></td>
</tr>
Later, if you need access to the state of each individual button, you can listen to the events on each individual component and register the effects of the clicks, or read the state of the button.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.