The React application I'm building has a TaskPanel component that uses a list of task names from its state to render a list of divs with Task components. The TaskPanel component uses this function in render() to make that happen:
showTasks() {
let taskList = [];
console.log(`in show tasks: ${Object.keys(this.state.tasks)}`);
console.log(`selected in show tasks: ${this.state.selected}`);
Object.keys(this.state.tasks).forEach((task_name, index) => {
taskList.push(
<div className="task_row_container">
<TaskCheck
task_name={task_name}
isSelected={this.state.selected.includes(task_name)}
handler={this.handleCheck}
/>
<Task
name={task_name}
data={this.state.tasks[task_name]}
key={index}
/>
<ActionTab
name={task_name}
data={this.state.tasks[task_name]}
key={task_name}
/>
</div>
);
});
return taskList;
}
Selecting the task to be deleted:

After pressing the delete button:

The problem arises when I select a task using one of the checkboxes and use the delete button. It is always the task that is last in the list that is visually removed. From debugging I've discovered that my checkboxes are working as intended. Inside my delete function I can see that it gets the proper name of the selected task to be deleted. It deletes the task just fine from the backend and the state seems to also update properly to reflect the task being deleted. Even in my showTasks function I can see that it is iterating through the correct remaining tasks.
This is how my delete function works:
deleteTask() {
var temp_tasks = this.state.tasks;
this.state.selected.forEach((task_name) => {
if (task_name in temp_tasks) {
delete temp_tasks[task_name];
}
});
this.setState({
...this.state,
selected: [],
allSelected: false,
tasks: temp_tasks,
});
console.log(this.state.tasks);
ipcRenderer.send("REACT_MODIFY_DATA", {
file: "tasks",
data: JSON.stringify(temp_tasks),
});
}
The frontend only updates to show the correct remaining tasks once I either fully refresh the browser, or navigate away and back to the TaskPanel. I also noticed from debugging that render() and showTasks seems to be called twice when I delete, and I have a feeling this could be related to my issue. I am at a loss for how to fix this... Any help is appreciated!
Please let me know if there's any other info I can provide to help!
[EDIT] This is my render function. It's a bit convoluted at the moment, but looking to minimize some of these event handlers:
render() {
return (
<div className="task_panel">
<div className="task_header">
<div className="task_header_title">Tasks</div>
<div className="task_button_grid">
<button
className="start_button"
onClick={(e) => this.startTasks(["test"])}
>
<div className="button_icon_container">
<svg
height="2vh"
className="button_icon"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path d="m405.28 201.19l-274.48-187.91c-12.676-8.684-25.448-13.28-36.064-13.28-20.524 0-33.22 16.472-33.22 44.044v406.12c0 27.54 12.68 43.98 33.156 43.98 10.632 0 23.2-4.6 35.904-13.308l274.61-187.9c17.66-12.104 27.44-28.392 27.44-45.884 4e-3 -17.48-9.664-33.764-27.344-45.864z" />
</svg>
</div>
Start
</button>
<button
className="stop_button"
onClick={(e) => console.log("Clicked Stop Button.")}
>
<div className="button_icon_container">
<svg
height="2.25vh"
className="button_icon"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M11.9999 0.333313C5.54825 0.333313 0.333252 5.54831 0.333252 12C0.333252 18.4516 5.54825 23.6666 11.9999 23.6666C18.4516 23.6666 23.6666 18.4516 23.6666 12C23.6666 5.54831 18.4516 0.333313 11.9999 0.333313ZM17.8333 16.1883L16.1883 17.8333L11.9999 13.645L7.81159 17.8333L6.16659 16.1883L10.3549 12L6.16659 7.81165L7.81159 6.16665L11.9999 10.355L16.1883 6.16665L17.8333 7.81165L13.6449 12L17.8333 16.1883Z" />
</svg>
</div>
Stop
</button>
<button
className="add_button"
onClick={(e) => {
this.showModal(e);
}}
>
<div className="button_icon_container">
<svg
height="2.25vh"
className="button_icon"
viewBox="0 0 18 18"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M18 10.2857H10.2857V18H7.71429V10.2857H0V7.71429H7.71429V0H10.2857V7.71429H18V10.2857Z" />
</svg>
</div>
Add
</button>
<button
className="edit_button"
onClick={(e) => console.log(this.state.selected)}
>
<div className="button_icon_container">
<svg
height="2.25vh"
className="button_icon"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M0 15.0422V19H3.95778L15.6306 7.32718L11.6728 3.36939L0 15.0422ZM18.6913 4.26649C19.1029 3.85488 19.1029 3.18997 18.6913 2.77836L16.2216 0.308707C15.81 -0.102902 15.1451 -0.102902 14.7335 0.308707L12.8021 2.24011L16.7599 6.19789L18.6913 4.26649Z" />
</svg>
</div>
Edit
</button>
<button
className="delete_button"
onClick={(e) => this.deleteTask()}
>
<div className="button_icon_container">
<svg
height="2.25vh"
className="button_icon"
viewBox="0 0 16 20"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M1.11111 17.7778C1.11111 19 2.11111 20 3.33333 20H12.2222C13.4444 20 14.4444 19 14.4444 17.7778V4.44444H1.11111V17.7778ZM15.5556 1.11111H11.6667L10.5556 0H5L3.88889 1.11111H0V3.33333H15.5556V1.11111Z" />
</svg>
</div>
Delete
</button>
</div>
</div>
<div className="task_container">
<div className="task_labels_header_container">
<div className="task_labels_header">
<div className="task_labels">
<input
type="checkbox"
onChange={(e) => this.handleCheckAll(e)}
checked={this.state.allSelected}
/>
</div>
<div className="task_labels">Name</div>
<div className="task_labels">Wallet</div>
<div className="task_labels">Contract Name</div>
<div className="task_labels">Mint Price</div>
<div className="task_labels">Max Gas Fee</div>
<div className="task_labels">Priority Fee</div>
<div className="task_labels">Start Time</div>
</div>
<div className="action_header_container">
<div className="action_header">Action</div>
</div>
</div>
<div className="task_list_container">{this.showTasks()}</div>
{this.state.modalVisible === true && (
<div className="add_modal_container">
<div className="add_modal">
<div className="add_modal_title">Add Task</div>
<div className="form_container">
<form className="add_modal_form">
<input
className="add_modal_text"
placeholder="Task Name"
type="text"
value={this.state.formTaskName}
onChange={this.handleTaskNameChange}
/>
<input
className="add_modal_text"
placeholder="Wallet Name"
type="text"
value={this.state.formWalletName}
onChange={this.handleWalletNameChange}
/>
<input
className="add_modal_text"
placeholder="Contract Name"
type="text"
value={this.state.formContractName}
onChange={this.handleContractNameChange}
/>
<input
className="add_modal_text"
placeholder="Mint Price"
type="text"
value={this.state.formTxnCost}
onChange={this.handleTxnCostChange}
/>
</form>
<form className="add_modal_form">
<input
className="add_modal_text"
placeholder="Max Gas Fee"
type="text"
value={this.state.formMaxFee}
onChange={this.handleMaxFeeChange}
/>
<input
className="add_modal_text"
placeholder="Max Priority Fee"
type="text"
value={this.state.formPriorityFee}
onChange={this.handlePriorityFeeChange}
/>
<input
className="add_modal_text"
placeholder="Mint Parameters"
type="text"
value={this.state.formMintParams}
onChange={this.handleMintParamsChange}
/>
<input
className="add_modal_text"
placeholder="Send on Pending Time"
type="text"
value={this.state.formSendPending}
onChange={this.handleSendPendingChange}
/>
</form>
</div>
<div className="add_modal_button_container">
<button
className="add_modal_cancel"
type="button"
onClick={(e) => this.hideModal(e)}
>
Cancel
</button>
<button
className="add_modal_finish"
type="button"
onClick={this.handleSubmit}
>
Add Task
</button>
</div>
</div>
</div>
)}
</div>
</div>
);
}
}
this.state.dict[key] = valueor is it better to have a temp dictionary and usethis.setStateto update state?