DEV Community

loading...

A simple Journal app (using React, localStorage and fun)

chaituknag profile image Naga Chaitanya Konada ・2 min read

Premise

I built a CodePen app that resembles a preliminary Journal app, using React, Bootstrap, Moment.js and localStorage as a DB.

What this post is about

I just want to share a few important concepts that you may be interested in.

JSON.stringify and JSON.parse

Whenever we are storing items in localStorage, we will have to stringify the value and parsing it while reading it.

const getEntriesFromStorage = () => JSON.parse(
    window.localStorage.getItem('journalEntries')
);
const setEntriesToStorage = items => 
    window.localStorage.setItem('journalEntries', JSON.stringify(items));
Enter fullscreen mode Exit fullscreen mode

Deleting an entry using Array.prototype.slice

When we have to delete an entry, we will create a new array out of the old one using the two features:

  1. Array.prototype.slice
  2. The ... spread operator

The index is the one of the item to delete in the array.

const newEntries = [...entries.slice(0, index), ...entries.slice(index+1)];
Enter fullscreen mode Exit fullscreen mode

Higher order delete entry click handler

To make the delete button work for each entry in the list of entries, we have to let the event handler know the item it has to delete in the DB, so we create a higher order function (one that returns another function which acts as the actual event handler).

  const handleDeleteClick = (index) => e => {
    deleteEntry(index);
  }
Enter fullscreen mode Exit fullscreen mode

Textarea in focus on page load

In the add Entry form, We want the focus onto the message textarea so that we can readily enter the message on page load, we can do a useEffect that runs only once per page load because of an empty array as second argument.

  useEffect(() => {
    fieldRef.current.focus();
  }, []);
Enter fullscreen mode Exit fullscreen mode

Moment.js .fromNow usage

When we show the date and time at which the entry was recorded, we can use a special feature of Moment.js called .fromNow() that converts the duration since the entry was recorded till now into human readable messages like "a few moments ago" and "2 minutes ago".

const itemDate = moment(item.date).fromNow();
Enter fullscreen mode Exit fullscreen mode

Custom hook (useJournal)

Any function that returns an array or object containing at least one of the built-in React hooks is known as a custom hook. In our case, we are abstracting the read-write to localStorage functionality in this custom hook so as to keep the functionality reusable and less messy in the component using it.

function useJournal() {
  const [entries, setEntries] = useState([]);

  const getEntriesFromStorage = () => JSON.parse(
    window.localStorage.getItem('journalEntries')
  );
  const setEntriesToStorage = items => 
  window.localStorage.setItem('journalEntries', JSON.stringify(items));
  useEffect(() => {
    const entriesFromStorage = getEntriesFromStorage();
    if(entriesFromStorage) {
      setEntries(entriesFromStorage);
    }
  }, []);

  const storeEntry = (entry) => {
    const newEntries = [entry, ...entries];
    setEntries(newEntries);
    setEntriesToStorage(newEntries);
  }

  const removeEntry = (index) => {
    const newEntries = [...entries.slice(0, index), ...entries.slice(index+1)];
    setEntries(newEntries);
    setEntriesToStorage(newEntries);
  }

  return [entries, storeEntry, removeEntry];
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Have a look at the CodePen (below) to understand what is done there and do suggest any simple changes that might improve the example greatly.

Discussion (3)

pic
Editor guide
Collapse
johnbwoodruff profile image
John Woodruff

Great post! Thanks for sharing this fun tiny app. I always love trying to build these micro versions of full blown apps.

On a side note have you heard of date-fns? It's a far smaller date manipulation library, alternative to moment. I've been using it and haven't noticed anything it's missing, it just makes my bundles so much smaller. Anyway you should check it out it's pretty great. :)

Thanks again for the fun post!

Collapse
chaituknag profile image
Naga Chaitanya Konada Author

Thank you so much for the appreciation, and date-fns I definitely heard good things about but never tried, let me try that as well.

Collapse
vikashask profile image
vikash verma • Edited

Awesome Naga. Really good short notes about JSON.stringify and JSON.parse and custom hook.

Thanks for sharing post.