My Experience at DubHacks 2019

October 12-13, 2019

At DubHacks 2019, my group and I created a web app that allowed users to track habits in under 24 hours. Based on the idea that it takes 66 days on average to form a habit, we wanted to create an application that helped track people's progress. Using React, we created an app that stores progress in the browser's local storage and allows users to check in daily. Overall, the hackathon was a great learning experience where we combined individual strengths towards a collaborative project.

Table of Contents

Showcase

Hackathon Experience

At DubHacks 2019, I had an incredible time. Although I had already attended a hackathon before, I was still blown away by the entire atmosphere and experience. Working on projects collaboratively at a hackathon, I got to bounce ideas between my team members and the other nearby teams. Hackathons are a truly creative and innovative place where people can come together to experiment and learn. In my group, we were all somewhat inexperienced. However, when we put our individual strengths together, we created a project that we were all proud of. From this, I gained insight into working collaboratively. Despite our own limitations, by combining our strengths, it eventually led us to a cohesive accomplishment.

Implementation

Since our group had working knowledge of various web technologies, we decided to use JavaScript. To implement this client-side web application, we utilized React, React Router, Semantic UI React, and the browser's local storage.

React

With React, we could create a web application with encapsulated components that could manage their own state. Since we had knowledge of JavaScript, we decided to explore something new and experiment using React.

Context

From the React Context documentation,

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

We noticed that our application revolved around an entire habits collection and passing it down in every view and component was tedious. To solve this, we used Context to pass the habits collection and a set of functions that allowed us to manipulate it. It was especially useful because it allowed us to pass this global store of habits in the different views we created.

To use Context, we have to create a Provider. This Provider component allows its children to actually access the Context. The HabitProvider component consists of all the functionality related to the habits collection. This essentially allowed us to view and manipulate our habits collection from any component that was nested within the HabitProvider.

React Router

React Router is a routing system created to work with React. It allows us to have different views or pages within our single-page application and have them routed to different URLs. By combining both React's Context and React Router, we were able to access and manipulate the habits collection on any view. This simplified our entire process since we had this global store of habits.

Semantic UI React

Since we had limited time, we opted to use Semantic UI React, a library that would allow us to easily add and integrate components into our existing code. By implementing the Semantic UI React components, we were able to create a frontend for our application rather quickly.

Local Storage

The main functionality of our application was that we allowed users to check in daily and track their progress. In order to do this, we had to find a way that would allow us to persist our data. Not wanting to add more complexity and create a backend server, we opted to store our user's habits into the browser's local storage. This allowed us to persist our data when the user left the page or restarted their browser. This also meant that users had to access the page on the same browser and that the data could be deleted if the cache was cleared.

First, we have to initialize our habits collection by either creating a new one, or retreiving it from our previous data.

/* Portion taken from the HabitProvider component in HabitContext.js */

/* Load habits from localStorage */
let initialHabits = JSON.parse((localStorage.getItem("habits") || "[]"));
let [habits, setHabits] = useState(initialHabits);

In this code, we get the habits from local storage and parse it if it exists. If it does not exist (the user has no previous data), then we default to an empty array. Then we initialize the state of our HabitProvider that is used throughout our application. We used JSON to save and persist our habits data. Since local storage can only store strings, JSON allows us to represent our habits collection in a string format.

We used the Effect Hook in React which allowed us to reset the progress on a habit if the user did not check in daily. To do this, we only ran the effect and validated the habits when the HabitProvider first loaded.

/* Portion taken from the HabitProvider component in HabitContext.js */

/* Resets streaks if missed on page reload */
useEffect(() => {
    setHabits((oldHabits) => {
        let todaysDate = new Date().setHours(0, 0, 0, 0);
        let newHabits = oldHabits.map((item) => {
            let lastCheckedInDate = new Date(item.lastCheckedIn).setHours(0, 0, 0, 0);
            let daysPast = (todaysDate - lastCheckedInDate) / (24 * 60 * 60 * 1000);
            if (daysPast > 1) {
                item.currentStreak = 0;
            }
            return item;
        })

        return newHabits;
    });
}, []);

By passing in an empty array for the second argument in the useEffect function, we can tell React to run this effect only once. To validate each habit's streak, we go through each habit and compare the last checked in date to the current date.

The Effect Hook also allowed us to update the local storage every time the habit collection changed.

/* Portion taken from the HabitProvider component in HabitContext.js */

/* Update localStorage every habits change */
useEffect(() => {
    localStorage.setItem("habits", JSON.stringify(habits));
}, [habits]);

Here, we tell React to update the local storage with a JSON representation of the habits collection every time it changes.

Conclusion

Overall, DubHacks 2019 was an amazing experience where I was able to experiment and learn in a collaborative project. Combining individual abilities towards learning something new, we were able to create a web application together in under 24 hours. From this experience, I was able to learn about creating a client-side application using React while also gaining experience in a collaborative setting.

Resources