Register to get access to free programming courses with interactive exercises

Data normalization JS: Frontend architecture

These applications almost always have a hierarchical structure. Let's take the list of posts on Hexlet as an example. Each post has an author and comments, which in turn have likes. This data can be represented as follows:

const posts = [
  {
    question: 'How do you write code?',
    likesCount: 2,
    comments: [
      {
        answer: 'Open the editor!',
        likesCount: 1,
        createdAt: '11-12-2022',
      },
      {
        answer: 'Sitting down!',
        likesCount: 3,
        createdAt: '11-12-2022',
      },
    ]
  },
  {
    question: 'Which is better: vim or emacs?',
    likesCount: 2,
    comments: [
      {
        answer: 'FAR the best!',
        likesCount: 100,
        createdAt: '11-12-2022',
      },
    ]
  }
];

The hierarchical representation of data reflects their structure well. You can see what's what at a glance. The data is easy to display and quite easy to change. Especially if the output on the screen is the same as their structure, and the data do not overlap with each other. Hexlet's topics are just such an example. Each topic lives its own independent life (there are some dependencies, but they don't concern the data themselves).

However, if the data are linked, the hierarchical structure becomes a problem. Imagine having to output the last 10 comments. How do you do that? I'll have to go through all the threads, take all the comments, combine them and look for the most recent ones. A frightening example:

const comments = posts.flatMap((p) => p.comments);
const sortedComments = comments.sort((c1, c2) => new Date(c2.createdAt) - new Date(c1.createdAt));
const lastComments = sortedComments.slice(0, 10);

The situation gets even worse when there are many-to-many connections. In this case, it is not clear what to put where. And there will always be situations where the resulting structure is not the best.

One way out of this situation is to start duplicating data. I.e., creating additional structures optimized for specific tasks. And while it makes sense in general, manually maintaining these structures will do no good. And in these databases, it's the databases themselves that are responsible for generating indexes. We as programmers don't have to worry about that. And here you have to implement additional synchronization in all stages, whether that's adding, changing and deleting.

Another way is to normalize the data, just like in relational databases. Imagine them as flat arrays. For example, like this:

// In a real application, everything will be stored in a single state object

const posts = [
  {
    id: 3,
    question: 'How do you write code?',
    likesCount: 2,
  },
  {
    id: 100
    question: 'Which is better: vim or emacs?',
    likesCount: 2,
  }
];

const comments = [
  {
    id: 1,
    postId: 3,
    answer: 'Open the editor!',
    likesCount: 1,
  },
  {
    id: 8,
    postId: 3,
    answer: 'Sitting down!',
    likesCount: 3,
  },
  {
    id: 3,
    postId: 100,
    answer: 'FAR the best!',
    likesCount: 100,
  },
]

If there are no clear boundaries between the data, and they depend on each other, then this structure is much more convenient. It easily allows you to perform general aggregations and special output options. It's important that the normalized data are not duplicated. In a well-organized state, data doesn't get repeated more than once.

Sometimes the opposite of normalization is used - denormalization, but this is more about the backend than the frontend.

However, when one door opens, another must close. Normalization will simplify everything in one place, but complicate it in another. Now you have to write the following code to extract the comments from a particular topic:

const postId = /* post identifier */;
const commentsForPost = comments.filter((c) => c.postId === postId);

There is no more code here than when choosing a particular post. But it's more complicated in an algorithmic sense, and more resources are spent on it. Whether this is a problem or not is an open question. As a rule, it isn't Frontend development very rarely operates with large quantities, such as tens or hundreds of thousands. Most often, the size of collections is limited to a hundred or so items.

To summarize, most mechanisms for storing state on the frontend recommend using the second storage method. And it doesn't matter if it's done within a framework or not. This approach is easier to scale and works well for all situations. Whereas the first approach will create a lot of problems the moment the data structure ceases to coincide with how it's displayed.


Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.bookmate">Bookmate</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.healthsamurai">Healthsamurai</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.dualboot">Dualboot</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.abbyy">Abbyy</span>
Suggested learning programs
profession
Development of front-end components for web applications
10 months
from scratch
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.