Doit, my obligatory React.js To-Do App
Because we've all got to start somewhere!
So, last week at my weekly meeting with my RCC crew, it was decided that my next step after my brushing up on Javascript (see my last few articles) would be to learn react.js. Make a simple to-do list, they said, it's easy, they said.
Except my first few days were... not nice. I think at one point I was passing 12 props into my delete button component: yikers!
That was one week ago: and now I'm done (for now) with a to-do list app, called doit (don't sue me I'm not monetizing it I'm sure the name is already taken but I pronounce mine 'doit' like 'doyt')
The app is usable, with an ugly but functional layout that works better on mobile than it does on desktop, but it works! Add to-do items with priority, cross them out, or delete them entirely. Yay.
So I figured I'd write a few articles about the pitfalls I fell into, and how I solved them. My status as a complete react.js newb probably makes me more adept at falling into these pitfalls, so maybe these will be helpful, who knows!
Data Structure for the Entries
The first step in designing an app like this is to figure out what data structure(s) will be worked with. I decided I wanted one data structure to hold all my to-do entries and related details with them, so I decided on an array of objects.
First, we need to make this a state, and I decided on making this state a part of the main App function.
const [entryArray, setEntryArray] = useState([])
This line here uses the useState hook to initialize our entryArray to an empty array, and initializes setEntryArray as the setter for this entryArray variable. More on that later. Next, on the handleSubmit function of our "add entry" button, we see something like this:
function handleSubmit(event) {
//Prevent the page from refreshing on submit
event.preventDefault();
//let dt = the current date/time in a formatted string
const dt = new Date().toLocaleString();
//If there's entry text being submitted, add a new entry.
// (Entries are objects, with text fields, an isDone bool,
// a dt representing datetime, and a priority field)
if (entryText) {
let newEntry = {
text: entryText,
isDone: false,
dt: dt,
priority: priorityVal
};
//Update entryArray state
entryArray.push(newEntry);
//Sort the array based on which priority is higher
entryArray.sort(function (a, b) {
return a.priority - b.priority;
});
//IMPORTANT: update the STATE of the entryArray variable via the setter
//function, setEntryArray. Using Slice to make sure the state updates.
setEntryArray(entryArray.slice());
This will add a new object with the relevant fields into the array of objects that we associate with entryArray, and update the state with it, after sorting it based on priority. Everything we need to do when we add a new entry! It takes the text value from the value of the controlled input text field, the datetime from the current date/time, and the priority value from the selected priority value in the form, and voila.
This array is iterated over in our main function to display the existent entries in order based on priority: we use a map function here to do so, creating a new ListEntry component with the relevant text and details of each entry to display it. We'll cover the details of that more in my next article.
The key here is that we're working with an array of objects: each object entry in the array is another To-Do list entry with all the given characteristics, and we can apply .map and .filter and whatnot to this array to accomplish different iteration-like goals.
So our entryArray, after a few passes of adding new entries, would look something like this:
[{ text: "Walk the Dog",
isDone: false,
dt: "3/31/2023 12:23.23", (or somesuch)
priority: "2"
}
{ text: "Walk 8 Miles",
isDone: true;
dt: "3/31/2023 12:25.34",
priority: "1"
}
{ text: "Watch 8 Mile",
isDone: false;
dt: "3/31/2023 8:34.31",
priority: "3"
}]
And when we iterate with map.... {entryArray.map((entry, idx) => {})) we have availability to every individual value through the dot operator (entry.text) for instance, and the index of the item in the array through the idx variable, which allows us to do just about anything we might need to do. Wonderful!
Next time, we'll talk about just how the entries are displayed, the other components (DeleteButton and CrossOutButton) and some of the other details, but this shall suffice for now as a basic rundown of how the data is modeled and handled in this quickie react app.