'Why does a checkbox get checked after another checkbox above gets removed?
I have an array of my clients' pending requests that I iterate through, creating a div with relevant information for each pending request. Within each div, there is an input with the type of checkbox. So, every pending request that gets added to the React DOM comes with a checkbox to remove it with.
Once a pending request's checkbox is checked and a button called "Mark As Resolved" is hit, the request gets removed from the array. The array, by the way, is stored in a React state called "pending" (this.state.pending). The interesting/weird thing that happens is that once a request is removed, the checkbox for the request immediately below becomes checked on its own for no apparent reason. To see it in action, please see this video: https://drive.google.com/file/d/1YONlJaflMdun8H-44TfkI97lZ-_J6yiY/view?usp=sharing
Here's how that div that contains the input looks:
<div className='pending-panel'>
{this.state.pending.map((pending, index) => {
return <div className='pending-container'>
{/* PENDING-SELECTOR */}
<input
className='pending-selector'
id={'pending-selector' + pending.id}
type='checkbox'
onClick={() => this.selectPending(pending)}>
</input>
<div
className='pending-request' key={index} onClick={() => this.openPending(pending)} id={pending.id}>
<span className='caret' id={'caret' + pending.id}>{this.state.pendingId === pending.id ? '\u25BC' : "\u25B2"}</span>
<h3 className='pending-title' id={"pending-title" + pending.id}>{this.state.updatePendingId === pending.id
? "Updating this request"
: `Request from ${pending.body.timestamp.toDate().toLocaleDateString('en-US')}, ${pending.body.timestamp.toDate().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`
}
</h3>
</div>
.......
This is the function that fires off when one of the checkboxes is clicked. I doubt it has any effect on the weird behavior in question, however. I am providing the code just in case.
selectPending(pending) {
console.log('select')
const pendingSelector = document.getElementById('pending-selector' + pending.id);
if (pendingSelector.checked) {
this.markAsResolvedRef.current.style.boxShadow = "0 0 2px 2px blue";
const pendingId = pending.id
this.setState({pendingArray: [...this.state.pendingArray, pendingId]})
} else {
const filteredCheckboxes = this.state.pending.filter(item => document.getElementById('pending-selector' + item.id).checked === true)
if (filteredCheckboxes.length === 0)
this.markAsResolvedRef.current.style.boxShadow = "0 0 2px 2px rgba(0, 0, 0, 0.24)";
this.setState({pendingArray: filteredCheckboxes})
}
}
This is the function behind the Mark As Resolved button. I am not seeing anything wrong with it either. It basically deletes the selected pending request from the database and moves it to a different location.
async markAsResolved () {
console.log('fired off')
const ref = firebase.firestore().collection('Chats').doc(this.state.userId).collection('Pending');
const array = [];
await ref.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log(doc.id)
// doc.data() is never undefined for query doc snapshots
this.state.pendingArray.forEach((pending) => {
console.log(pending)
if (pending === doc.id) {
console.log('match')
array.push({id: doc.id, body: doc.data()})
doc.ref.delete();
}
})
});
});
const ref2 = firebase.firestore().collection('Chats').doc(this.state.userId).collection('Resolved');
array.forEach(async (pending) => {
await ref2.doc(pending.id).set({
body: pending.body,
timestamp: new Date()
}, {merge: true})
.then(() => {
console.log("Document successfully written!");
})
.catch((error) => {
console.error("Error writing document: ", error);
});
})
The following is part of a Firebase event listener that listens to changes in the Firestore database like add, modify or delete. So, once the Mark As Resolved button is pressed, the selected pending request is deleted from the database and, hence, the following function runs and I update the pending react state by removing the deleted pending request so it does not show in the React DOM or the front end any more.
const ref2 = firebase.firestore().collection('Chats').doc(doc.uid).collection('Pending');
const query2 = ref2.orderBy('timestamp', 'desc');
this.unsubFromPending = query2.onSnapshot((snapshot) => {
if (snapshot.empty) {
console.log("no pending requests")
}
snapshot.docChanges().forEach((change) => {
if (change.type === "removed") {
const filteredPending = this.state.pending.filter(pending => pending.id !== change.doc.id)
this.setState({pending: filteredPending})
const sorted = this.state.pending.sort((a, b) => b.body.timestamp.valueOf() - a.body.timestamp.valueOf());
this.setState({pending: sorted})
}
My goal is to end this weird behavior of a lower checkbox getting checked on its own when it was not pressed.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
