Building a simple ToDo list app in ReactJS. Below is my Add Task functional component:
import React, { useState } from "react";
import TaskDataService from "../services/task.service";
import DatePicker from 'react-datepicker'
import FadeIn from 'react-fade-in';
import "react-datepicker/dist/react-datepicker.css";
import 'bootstrap/dist/css/bootstrap.min.css';
const AddTask = () => {
const initialTaskState = {
id: null,
title: "",
description: "",
completed: false,
startDate: new Date()
};
const [task, setTask] = useState(initialTaskState);
const [submitted, setSubmitted] = useState(false);
const handleInputChange = event => {
const { name, value } = event.target;
setTask({ ...task, [name]: value });
};
const saveTask = () => {
var data = {
title: task.title,
description: task.description,
startDate: task.startDate
};
TaskDataService.create(data)
.then(response => {
setTask({
id: response.data.id,
title: response.data.title,
description: response.data.description,
completed: response.data.completed,
startDate: response.data.startDate
});
setSubmitted(true);
console.log(response.data);
})
.catch(e => {
console.log(e);
});
};
const newTask = () => {
setTask(initialTaskState);
setSubmitted(false);
};
return (
<FadeIn>
<div className="submit-form">
{submitted ? (
<div>
<h4>Task submitted successfully!</h4>
<button className="btn btn-success" onClick={newTask}>
Add
</button>
</div>
) : (
<div>
<div className="form-group">
<label htmlFor="title">Title</label>
<input
type="text"
className="form-control"
id="title"
required
value={task.title}
onChange={handleInputChange}
name="title"
/>
</div>
<div className="form-group">
<label htmlFor="description">Description</label>
<input
type="text"
className="form-control"
id="description"
required
value={task.description}
onChange={handleInputChange}
name="description"
/>
</div>
<div className="form-group">
<label htmlFor="startDate">Start Date</label>
<DatePicker
selected={ task.startDate }
onChange={date => handleInputChange({target: {value: date.toISOString().split("T")[0], name: 'startDate'}})}
name="startDate"
dateFormat="yyyy-MM-dd"
/>
</div>
<button onClick={saveTask} className="btn btn-success">
Submit
</button>
</div>
)}
</div>
</FadeIn>
);
}
export default AddTask;
When I try to select a date from the Datepicker calendar, app rendering crashes. There are a few errors but it looks like the main one is "Uncaught RangeError: Invalid time value". However, the task is successfully added to the database and I can view it upon reloading the app. But for whatever case, it crashes upon submit.
In contrast, this is my standalone Task component which also contains code for editing an existing task. In that component, everything works 100%. I can open the Datepicker calendar on the selected task, select a new date, and submit it succesfully with zero problems:
import React, { useState, useEffect } from "react";
import { useParams, useNavigate } from "react-router-dom";
import TaskDataService from "../services/task.service";
import DatePicker from 'react-datepicker';
import FadeIn from 'react-fade-in';
const Task = props => {
const { id } = useParams();
let navigate = useNavigate();
const initialTaskState = {
id: null,
title: "",
description: "",
completed: false,
startDate: new Date(),
};
const [currentTask, setCurrentTask] = useState(initialTaskState);
const [message, setMessage] = useState("");
const getTask = id => {
TaskDataService.get(id)
.then(response => {
setCurrentTask(response.data);
console.log(response.data);
})
.catch(e => {
console.log(e);
});
};
useEffect(() => {
if (id)
getTask(id);
}, [id]);
const handleInputChange = event => {
const { name ,value } = event.target;
setCurrentTask({ ...currentTask, [name]: value });
};
const updateCompleted = status => {
var data = {
id: currentTask.id,
title: currentTask.title,
description: currentTask.description,
completed: currentTask.completed,
startDate: currentTask.startDate
};
TaskDataService.update(currentTask.id, data)
.then(response => {
setCurrentTask({ ...currentTask, completed: status });
console.log(response.data);
})
.catch(e => {
console.log(e);
});
};
const updateTask = () => {
TaskDataService.update(currentTask.id, currentTask)
.then(response => {
console.log(response.data);
setMessage("The task was updated successfully!");
})
.catch(e => {
console.log(e);
});
};
const deleteTask = () => {
TaskDataService.remove(currentTask.id)
.then(response => {
console.log(response.data);
navigate("/tasks");
})
.catch(e => {
console.log(e);
});
};
return (
<FadeIn>
<div>
{currentTask ? (
<div className="edit-form">
<h4>Task</h4>
<form>
<div className="form-group">
<label htmlFor="title">Title</label>
<input
type="text"
className="form-control"
id="title"
value={currentTask.title}
onChange={handleInputChange}
/>
</div>
<div className="form-group">
<label htmlFor="description">Description</label>
<input
type="text"
className="form-control"
id="description"
value={currentTask.description}
onChange={handleInputChange}
/>
</div>
<div className="form-group">
<label>
<strong>Status:</strong>
</label>
{currentTask.completed ? "Completed" : "Pending"}
</div>
<div className="form-group">
<label htmlFor="startDate">Start Date</label>
<DatePicker
onChange={date => handleInputChange({target: {value: date.toISOString().split("T")[0], name: 'startDate'}})}
name="startDate"
dateFormat="yyyy-MM-dd"
value={currentTask.startDate.toString().split("T")[0]}
/>
</div>
</form>
{currentTask.completed ? (
<button
className="badge badge-primary mr-2"
onClick={() => updateCompleted(false)}
>
Mark Pending
</button>
) : (
<button
className="badge badge-primary mr-2"
onClick={() => updateCompleted(true)}
>
Mark Complete
</button>
)}
<button
className="badge badge-danger mr-2"
onClick={deleteTask}
>
Delete
</button>
<button
type="submit"
className="badge badge-success"
onClick={updateTask}
>
Update
</button>
<p>{message}</p>
</div>
) : (
<div>
<br />
<p>Please click on a Task...</p>
</div>
)}
</div>
</FadeIn>
);
}
export default Task;
Done a lot of testing and research but no dice. Any ideas?