<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Davor Tvorić</title>
    <description>The latest articles on DEV Community by Davor Tvorić (@shockwavee).</description>
    <link>https://dev.to/shockwavee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F336991%2Fd23783a4-71eb-499d-806e-7c5a247616be.jpeg</url>
      <title>DEV Community: Davor Tvorić</title>
      <link>https://dev.to/shockwavee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shockwavee"/>
    <language>en</language>
    <item>
      <title>Decoupling Deployment From Release With Feature Toggles</title>
      <dc:creator>Davor Tvorić</dc:creator>
      <pubDate>Wed, 06 Dec 2023 09:47:41 +0000</pubDate>
      <link>https://dev.to/productive/decoupling-deployment-from-release-with-feature-toggles-7lo</link>
      <guid>https://dev.to/productive/decoupling-deployment-from-release-with-feature-toggles-7lo</guid>
      <description>&lt;p&gt;Deploying new features is a nerve-racking task, &lt;strong&gt;but it must be done&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s an issue we’ve all faced or will inevitably face in our careers. Allow me to set the scene…&lt;/p&gt;

&lt;p&gt;You’ve finished your work on some features, fixed some bugs, etc. You’re feeling good because some features were a bit more complicated. You decide it’s high time to let your users experience these changes. You bundle up all your teams’ changes and deploy them to the production server. A couple of hours later, disaster strikes! There’s a critical bug on a feature you’ve worked on. Now, you have to revert to the old version of the application or deploy a new one, but without your changes.&lt;/p&gt;

&lt;p&gt;As these situations can have a huge impact, reacting quickly is key. Unfortunately, developers usually learn how to handle this situation once it happens, so it only prolongs the agony.&lt;/p&gt;

&lt;p&gt;Deploying and releasing at the same time isn’t such an uncommon practice because, at the beginning of a project, you want your users to see the changes immediately. Many projects continue using this process, but as the project grows, it makes sense to decouple the deployment of the code and the release process (activating changes to users).&lt;/p&gt;

&lt;p&gt;Even if this hasn’t happened to you yet, we can all agree that it’s a very stressful situation, and establishing a process for handling this is something you want to do ahead of time. &lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;how much&lt;/strong&gt; ahead of time are we talking about here?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyqbgtbf0icop8zojak7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyqbgtbf0icop8zojak7.png" alt="An image of Batman thinking"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature toggles (aka feature flags)
&lt;/h2&gt;

&lt;p&gt;There are many ways to handle these types of outages, and it’s important to establish a rollback procedure. In addition to that, we also use something called &lt;strong&gt;feature toggles&lt;/strong&gt;. It’s not something unique to us, but it’s a pretty sweet thing to have in your toolbox. For those unfamiliar with feature toggles, it’s a mechanism that allows you to turn a feature on or off for a user &lt;strong&gt;without needing to deploy the whole application&lt;/strong&gt;. It’s really simple, but it’s huge!&lt;/p&gt;

&lt;p&gt;Although it’s called a “feature toggle”, it doesn’t necessarily mean that you have to use them for features only. You can use them basically for anything. Whether it’s A/B testing, refactoring a part of the screen, or navigating a user to a different page entirely! I’m sure you can think of a couple of more examples that would be useful to you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbghum3mrk19rx7j4dza7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbghum3mrk19rx7j4dza7.png" alt="An example of some feature toggles in Productive"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This also allows us to oversee which users can access a certain change. This is helpful when trying to collect feedback or just observing how users interact with something you’ve developed. Once you’ve established your feature toggle system, you don’t need to put in continuous work to keep it going. It’s also a great way to manage the lifecycle of the change by progressively rolling it out to your canary, beta, and all users! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6zbx5fajn9uu8xxlj1v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6zbx5fajn9uu8xxlj1v.png" alt="An image that represents a possible segmentation of users, ranging from internal users, beta release, early adopters and all users"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You gain a lot more control over who sees what, and the best part is that turning toggles on or off can be done by anyone! Someone like a product manager or customer support person could decide to turn a toggle on because it’s just something that the customer needs. After a feature has been fully developed, the toggle can be globally released to all customers, and everyone can enjoy the stable version.&lt;/p&gt;

&lt;p&gt;The number of annoyed users will decrease, and valuable feedback on changes will increase. &lt;/p&gt;

&lt;p&gt;It’s also worth mentioning that you can base your whole QA process on the toggles. We can test a change by turning a toggle on, gathering feedback, and then turning the toggle off. When you have such fine-grained control, testing on production isn’t a big deal! We also use these toggles in other environments, so you can isolate a change to a specific set of users on any server.&lt;/p&gt;

&lt;p&gt;It’s a win-win for everyone!&lt;/p&gt;

&lt;h2&gt;
  
  
  Okay, but what about development?
&lt;/h2&gt;

&lt;p&gt;The main question that’s probably going around in your head is how the feature toggles affect the development of a feature.&lt;/p&gt;

&lt;p&gt;Feature toggles do complicate things a bit when writing code, but if you spend some time on planning, it can be done elegantly in most cases. You must be careful to add every change behind the toggle so nothing leaks when the toggle isn’t turned on. Other people working on the feature must also be aware of using the toggle since it probably will span through multiple files and can sometimes be forgotten.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8zs94wzodwqkm4vjif5t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8zs94wzodwqkm4vjif5t.png" alt="A simple code example that adds a calculates a currency conversion on a cost if a toggle is turned on"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometimes, it’s not that complicated, but you gain a lot. As I’ve already mentioned, it can be used for basically anything, and complexity may increase, but it really is worth it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8owslxug3cic5fonqjws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8owslxug3cic5fonqjws.png" alt="An image with two code examples, one showing a possible handling for refactoring and another one navigating to another screen based on a feature toggle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The added complexity isn’t such a big drawback. You’re getting a lot more out of feature toggles, and if that means that developers have to be a bit more careful when writing and reviewing code, so be it. It’s much less stressful for a developer when they know a feature can be turned off if it’s causing problems. This doesn’t mean we approve of sloppy code, but sometimes, these things happen.&lt;/p&gt;

&lt;p&gt;To conclude, feature toggles (once established) don’t affect the development process as much, but they offer a lot in return.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alleviating the downsides
&lt;/h2&gt;

&lt;p&gt;The first one does introduce technical debt, but if we create a task for deleting a toggle after it’s been globally released, we can be sure that it will be deleted as soon as possible. The person who created the toggle is responsible for deleting it, which is a great way to handle this efficiently. In any case, deleting a toggle usually takes significantly less time than developing it!&lt;/p&gt;

&lt;p&gt;As for the other issue, there are two ways to handle this. We can do either of these two:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Release the first toggle globally and delete its references in the code if the feature is ready to be released or&lt;/li&gt;
&lt;li&gt;Merge the toggles and consider them to be the same feature from now on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s not an ideal situation, but it can happen. The solution mostly depends on the state of the features, so it’s impossible to determine the best way without knowing all the facts. Either way, both solutions can simplify things for development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decisions, decisions
&lt;/h2&gt;

&lt;p&gt;For us, implementing feature toggles was a no-brainer. Considering all of the benefits like the control, progressive rollouts, and others, it seriously outweighs the downsides it introduces. Even the downsides can be managed to an extent.&lt;/p&gt;

&lt;p&gt;It’s important that &lt;strong&gt;everyone&lt;/strong&gt; in the company understands the whole process and embraces why we’re doing it in such a way. It’s an essential part of a company like ours since every department is involved in the release process of product updates. Once people are aware of this, building an admin system to control this is up to you and your company’s needs. &lt;/p&gt;

&lt;p&gt;Here’s an example of our own. We call it the “Backoffice”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3gjnv4pmwapdn6zi7xf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3gjnv4pmwapdn6zi7xf.png" alt="An example of our "&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;THERE ARE ~200 ACTIVE FEATURE TOGGLES IN OUR CODEBASE&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a developer, I’m grateful we can release features quickly and stress-free, knowing we have some wiggle room.&lt;/p&gt;

&lt;p&gt;As for you, I hope I’ve shown you why it’s a good idea to think about something like this if you don’t use a similar mechanism. If you need a bit more convincing, you can read more about it in &lt;a href="https://martinfowler.com/articles/feature-toggles.html" rel="noopener noreferrer"&gt;an article by Martin Fowler&lt;/a&gt;! Even if you’re not in a position to make your feature toggle system, there are a lot of external tools and libraries that might help you implement the same!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>buildingproductive</category>
      <category>deployment</category>
      <category>programming</category>
    </item>
    <item>
      <title>Check yo' project structure before you wreck yo' project structure</title>
      <dc:creator>Davor Tvorić</dc:creator>
      <pubDate>Mon, 04 Apr 2022 09:48:50 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/check-yo-project-structure-before-you-wreck-yo-project-structure-3egp</link>
      <guid>https://dev.to/bornfightcompany/check-yo-project-structure-before-you-wreck-yo-project-structure-3egp</guid>
      <description>&lt;p&gt;I gotta admit, when it came to structuring a frontend project, I didn't really know why people considered it that important. I've mostly been working on smaller projects either alone or with 2-3 people. The projects' structure didn't matter all that much because they were abandoned as soon as we were finished with the project. With this kind of experience you might get lulled into the feeling that the default setup is all that you need.&lt;br&gt;
I realized there's a lot more than meets the eye when I started working on an existing project that was a couple of years old. Just imagine being plopped in a foreign structure where you have to think about &lt;strong&gt;every little detail&lt;/strong&gt; and question yourself constantly!&lt;br&gt;
I started thinking a lot more about where I'd place a function, partial or a simple object. By just spending some time thinking about what would be the most logical solution, I've (hopefully) improved mine and everyone else's developer experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1267hagcwy749fo1fj3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1267hagcwy749fo1fj3.jpg" alt="Developer experience"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The catch is that I still have a lot to learn. I'm sure there's some things I haven't even considered because they're manageable at the time. But I don't see that as a bad thing, since that's something that could probably be improved. That's why I think it's important that you review how you structure your projects once in a while.&lt;/p&gt;

&lt;p&gt;In this article, I'll explain why we've had the idea for a standard project structure within our team. My experience is related to frontend, but you might find something interesting even if you work in something else! But if you're in need of an actual structure, I'll be showing that in some other post.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can you condense complex project structures into a single template?
&lt;/h2&gt;

&lt;p&gt;Our projects' structure can vary a lot depending on the length of the project, the complexity, the features, and a number of other factors. However, I think we can make a generic structure which would work great in most cases. Now you're probably thinking, what about existing projects? It might be really complex (and inefficient) to change the whole structure in an existing project, but who says that you have to change absolutely everything? If you're going to work on a project for some time, why not make it easier for yourself if it's possible? After all, you've probably gathered a lot of knowledge throughout the years and could surely improve on the parts you designed at the beginning of the project.&lt;/p&gt;

&lt;p&gt;Tackling this problem might not even be as complicated as you might think. Just writing down and explaining each folder/file will give you insight about your current situation.&lt;br&gt;
From there you can easily see whether the decisions you made make sense! When I did this, it really felt like a game of Sudoku. When it seems like there's nothing else that can be done, you stumble upon a couple of smaller things here and there and, suddenly, a huge playing field opens up. That's my method for handling larger and older projects that are in time for a tune up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fc.tenor.com%2FaEbRRiginLwAAAAC%2Fmechanic-hammer.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fc.tenor.com%2FaEbRRiginLwAAAAC%2Fmechanic-hammer.gif" alt="Clarkson hitting a car with a hammer"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Many projects, even more factors, but not enough resources
&lt;/h2&gt;

&lt;p&gt;I work in an agency, but we work on projects of varying lengths. Some are done in a month's time and some are worked on for years. We're not limited to one technology, so that's also another factor. That's just a couple of things, but our structures can be wildly different. This means that each time you switch projects you have to get used to a different structure, as well. By not having a defined standard within the team, it meant that new projects would succumb to the same fate. That's more cognitive load that you don't want to have.&lt;br&gt;
To counter that, we've researched which structure would fit us the best. Most of our focus was on scalability, readability, and extendibility. That's a lot of &lt;em&gt;-bilitys&lt;/em&gt;, but in simpler terms we wanted to make sure that the project structure we made is easy to understand, use and improve. Sounds really simple, but to find something concrete on the Internet proved to be somewhat of a tough task. We were defining this structure for our frontend projects where the technologies are relatively young. Therefore, there's a lot of resources that show their ideas on really small examples with little experience in larger projects. It also doesn't help that only some use actual architectural patterns that are commonly used in software development.&lt;br&gt;
We did manage to find some resources that really helped us out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://blog.webf.zone/contemporary-front-end-architectures-fb5b500b0231" rel="noopener noreferrer"&gt;Contemporary Front-end Architectures&lt;/a&gt; by Harshal Patil&lt;/li&gt;
&lt;li&gt;&lt;a href="https://infinum.com/handbook/frontend/react/project-structure" rel="noopener noreferrer"&gt;Infinum Frontend Handbook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://michalzalecki.com/elegant-frontend-architecture/" rel="noopener noreferrer"&gt;How to structure frontend application&lt;/a&gt; by Michal Zalecki&lt;/li&gt;
&lt;li&gt;&lt;a href="https://angular.io/guide/styleguide#folders-by-feature-structure" rel="noopener noreferrer"&gt;Folders-by-feature structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactpatterns.com/#container-component" rel="noopener noreferrer"&gt;Container component&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's a lot to learn from each resource, but we didn't use every single thing from them. Each part was discussed and made sure that it really worked for us. It helped that we could decide as a team because each of us had some experience in something the others didn't, so it's important not to dismiss anyone's opinion.&lt;br&gt;
After defining a structure, there's two last steps that were incredibly important and made everything click:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Explain each segment so that someone with less experience can understand it with relative ease&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Just by using your explanation from the last step, create a smaller app to test out your structure&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackernoon.com%2Fimages%2F1%2Avrxt-ULqMURtcTHQ3ayfoA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhackernoon.com%2Fimages%2F1%2Avrxt-ULqMURtcTHQ3ayfoA.gif" alt="Salt bae"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These steps were vital to adding most of the finishing touches. If we hadn't done them, we would have shot our own leg when we started a new project. It makes sense testing out what you did, but it is tempting to skip this part since you've already done the majority of the work. It will also help you to objectively look at the work you've done. Don't forget that everything can be improved!&lt;/p&gt;

&lt;h2&gt;
  
  
  Final words
&lt;/h2&gt;

&lt;p&gt;Following this plan we came up with a concise &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;CRA&lt;/a&gt; template (and Vue template) with a detailed README. Now we're able to preserve the same project structure throughout multiple projects and relieve ourselves of the cognitive load when switching to other projects.&lt;br&gt;
This does not mean that our work is over, but it should be less of a hassle to have a great foundation and improve everything from here.&lt;/p&gt;

&lt;p&gt;And if that doesn't sound great, I don't know what does!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>engineeringmonday</category>
      <category>javascript</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How to work as a solo frontend developer</title>
      <dc:creator>Davor Tvorić</dc:creator>
      <pubDate>Mon, 08 Nov 2021 07:45:25 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/how-to-work-as-a-solo-frontend-developer-dhp</link>
      <guid>https://dev.to/bornfightcompany/how-to-work-as-a-solo-frontend-developer-dhp</guid>
      <description>&lt;p&gt;Working in a team is great. You can progress really fast and learn a lot from your colleagues. Having another set of eyes to proof check your work is a godsend because it can prevent silly things being deployed to production.&lt;br&gt;
But, sometimes, life happens and you have to work alone on a project. Be it a specific technology, budget reasons or something entirely else, it doesn't really matter. Working alone doesn't mean it'll suck or be really stressful if you keep yourself in check.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckoq7wemuqbwmb426o0u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckoq7wemuqbwmb426o0u.png" alt="To do list"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I worked on a couple of projects as a solo frontend developer, but I rarely had the feeling like I couldn't do it or that I maybe didn't learn as much as I could have. If you "act" like there is a whole team involved (or that someone new will be joining you on the project), that can force you not to take shortcuts and do everything properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't be lazy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Avoid shortcuts
&lt;/h3&gt;

&lt;p&gt;It's really easy to skip a couple of steps when working alone because, honestly, is anyone going to notice? The answer should be yes, you'll notice it!&lt;br&gt;
Opening a pull request that will be merged to master immediately might seem illogical, but having everything consistent will surely help you out in the long run. On top of that, you might notice something wrong when you're doing a once-over.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep your code neat
&lt;/h3&gt;

&lt;p&gt;Keeping your code neat is something you also shouldn’t skimp out on. Linters, prettiers and everything else should be setup as if you were in a team!&lt;/p&gt;

&lt;h3&gt;
  
  
  Be your own QA
&lt;/h3&gt;

&lt;p&gt;Writing tests is a no-brainer. It's always a great relief knowing that stuff works even after a refactor. Not having to constantly think about that will allow you to focus on more important things! That shouldn't change even if you're working alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation!
&lt;/h2&gt;

&lt;p&gt;It might be boring, but if you don't do it, nobody will. At a first glance, it doesn't seem important since you're the only one that will be reading it. I can tell you that I know for a fact that the future you will thank you for it. It's unrealistic to expect you'll remember every little detail, even though you've written everything yourself. Having a good documentation means that some of the mental burden can be relieved because you can refer to it at any time.&lt;br&gt;
Heck, something might even change within the project and your new teammate will be even faster with the onboarding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ask for help
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Collaborate with other frontend developers
&lt;/h3&gt;

&lt;p&gt;I have the benefit that there are other brilliant teammates on other projects. They might not know the domain of my project, but they can offer technical help if you explain it to them. Try to make it easy for them to understand it, and I’m sure that you’ll get new insights. The same goes for asking for help online. Just because you're alone on the project doesn't mean that you have to do everything by yourself.&lt;br&gt;
If you have work colleagues, it's not a bad idea to assign them on a pull request once in a while. You might be surprised how tunnel-visioned you can get!&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn about the domain from backend
&lt;/h3&gt;

&lt;p&gt;If there's a backend, I'm sure you can discuss domain issues with them, as well. They probably know a lot and it's a good idea to double-check with them. You might learn about something you weren't aware of!&lt;/p&gt;

&lt;h2&gt;
  
  
  Improve wherever you can
&lt;/h2&gt;

&lt;p&gt;Now that you're alone on the project, you can do anything to improve your development experience. If there is a task that needs to be automated, why wouldn't you automate it? If you can get the budget for it, you'll save time and you'll learn something new. This is a great opportunity to make up for not learning from your teammates. Something that a senior colleague always set up can now be done by you. It might seem  daunting if it's out of your comfort zone, but hey, how else are you going to learn?&lt;br&gt;
From personal experience, these situations taught me some skills I would rarely have the time to research in other projects.&lt;/p&gt;

&lt;p&gt;By sticking to these tips, I've been able to maximise my learning and do quality work as much as I could. Not having a teammate doesn't mean that you really have to be isolated from everything else. And, who knows, you might even get someone working on a project by your side so you want to be proud of what you're capable of doing all on your own, right?&lt;/p&gt;

</description>
      <category>engineeringmonday</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Try to avoid comments (most of the time)</title>
      <dc:creator>Davor Tvorić</dc:creator>
      <pubDate>Mon, 31 May 2021 13:36:50 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/try-to-avoid-comments-most-of-the-time-2f6a</link>
      <guid>https://dev.to/bornfightcompany/try-to-avoid-comments-most-of-the-time-2f6a</guid>
      <description>&lt;p&gt;Writing down a comment when you're coding might seem like you're going to help yourself or someone that might stumble upon your code, but, in reality, it might cause confusion and make your code less readable. If you're just starting out with coding, you sometimes feel that you need to comment every line to get your point across. That's probably not the case most of the time and you're probably just adding unnecessary noise to your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code explanation
&lt;/h2&gt;

&lt;p&gt;If possible, try to use the time you would spend on writing a comment on coming up with better naming or clearer code structures. Take a look at this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// check if employee can receive overtime pay&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isFullTime&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workHours&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of relying on the comment to explain the condition, it would be much wiser to create a function with a clear name that does this check&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isEmployeeEligibleForOvertimePay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isFullTime&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workHours&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isEmployeeEligibleForOvertimePay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's now possible to reuse this small piece of code, as well as not have any doubts what this condition does. This might be a much larger condition, but a name might be sufficient enough to be aware what it's doing.&lt;/p&gt;

&lt;p&gt;Of course, there is a case where it's very difficult to come up with a meaningful name or it's just not possible. In that case a comment would be helpful, but you should have that as a last resort.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outdated comments
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;insertData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// updates the current user data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you've been working on some older projects, something like this might've popped up. You can see that some data is being inserted, but the comment says otherwise. The comment might be right, although someone could have forgotten to delete it. This causes you to doubt the code and you're forced to check what's really going on in the insert method.&lt;/p&gt;

&lt;p&gt;To prevent this, it's probably better to rename the functions to better represent their functionality and delete the unnecessary comment.&lt;br&gt;
This is something that might happen with any comment. If someone forgets to update the comment after a couple of changes, another person can't be sure what's right or not. It's not a critical mistake and nothing will break because of this, but you might spend a couple of minutes/hours until you find out the truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redundant comments
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// checks whether the student lives in a dorm&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;student&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;livesInDorm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I think we can all agree that these kinds of comments are totally unnecessary. You might feel better that you've written a couple lines of comments, but this doesn't help anyone when it's obvious what's happening&lt;/p&gt;

&lt;h2&gt;
  
  
  Separators
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ---------------&lt;/span&gt;
&lt;span class="c1"&gt;// VARIABLES&lt;/span&gt;
&lt;span class="c1"&gt;// ---------------&lt;/span&gt;
&lt;span class="nv"&gt;$blue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#1257ab&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This could be debated, but I think that the file structure should mandate where something belongs. By having these kinds of comments, you're just breaking up the flow of the code and not adding much value. If this is something that occurs a lot, having a defined standard with vertical formatting might have a much more appealing look.&lt;/p&gt;

&lt;p&gt;Some people are more of a visual type, so separators can come in handy to visualize the various parts of a file, but I would still stay away from them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Commented code
&lt;/h2&gt;

&lt;p&gt;Nowadays, there's probably very little reason to keep commented out code in your codebase, especially if you're using a version control system. Anyone that will come upon the commented code won't be bothered to delete it because they haven't written in in the first place.&lt;br&gt;
That will just perpetuate the old code into newer versions until it won't even work if you comment it out.&lt;/p&gt;

&lt;p&gt;Do yourself a favour and delete the commented code. If you'll really need it, you can get it from your VCS' history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Having comments in your codebase is something that requires constant attention. When you update a function, you must make sure you've updated its comment as well. That's why most of the comments you write go stale and just confuse you next time you bump into them.&lt;br&gt;
By spending more time on naming your variables and functions, extracting a piece of code and adding vertical or horizontal formatting, you might even avoid the need for comments.&lt;/p&gt;

&lt;p&gt;Even though I've shown the types of comments you should avoid, there are cases where it's a good idea to leave a comment (but not that many!). &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;leaving a warning on a complicated feature that can't be managed with proper names is always a good idea&lt;/li&gt;
&lt;li&gt;documentation/legal comments in public code&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>engineeringmonday</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Why you shouldn't mix levels of abstraction in your functions</title>
      <dc:creator>Davor Tvorić</dc:creator>
      <pubDate>Mon, 11 Jan 2021 16:30:28 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/why-you-shouldn-t-mix-levels-of-abstraction-in-your-functions-332f</link>
      <guid>https://dev.to/bornfightcompany/why-you-shouldn-t-mix-levels-of-abstraction-in-your-functions-332f</guid>
      <description>&lt;p&gt;For some time now, I was convinced I could be writing more readable code. Because of a high paced tempo that is working in an agency, I had an excuse not to invest more time in readability. Or so I thought.&lt;/p&gt;

&lt;p&gt;You can come up with all sorts of excuses to assure yourself that your code is good enough and that someone else will understand it perfectly in a couple of months. That won't help you out when you actually get stuck in a trap you set up yourself. Okay, this sounds really dramatic, but I hope you get the point!&lt;br&gt;
By writing clean code, you'll be helping someone continue writing code after you, but you'll help yourself as well. The main problem for me is that I can recognize good code, but when I start coding, all of that falls apart because I'm not sure what really makes code good.&lt;/p&gt;

&lt;p&gt;One of the concepts I've picked up is the level of abstraction (in your functions). Take a look at this piece of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function createUser(username, password) {
    if (username.trim().length &amp;lt;= 2) {
        console.error('Username too short.');
        return;
    }

    if (password.length &amp;lt;= 6 || password.length &amp;gt; 30) {
        console.error('Password must be longer than 6 characters and shorter than 30');
        return;
    }

    const user = {
        username,
        password
    };
    database.insert(user);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's nothing too complex, right? You can pretty easily determine what this function is doing and what validations it's checking. But we can make it even easier to read for other developers.&lt;br&gt;
This is an example of mixing levels of abstraction which we should remedy, if possible. The thing why this might seem a bit off is because we're having some low-level checks (length of username and password) and some high-level functions which handle inserting some data in a database. To make this function more readable, we should try to even out the levels of abstraction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function createUser(username, password) {
    try {
        validateUserData(username, password)
    } catch(error) {
        showErrorMessage(error);
        return;
    }

    const user = {
        username,
        password
    };
    database.insert(user);
}

function validateUserData(username, password) {
    if (!isUsernameValid(username)) {
        throw new Error('Username too short');
    }

    if (!isPasswordValid(password)) {
        throw new Error('Password must be longer than 6 characters and shorter than 30');
    }
}

function isUsernameValid(username) {
    return username.trim().length &amp;gt; 2;
}

function isPasswordValid(password) {
    return password.length &amp;gt; 6 &amp;amp;&amp;amp; password.length &amp;lt;= 30;
}

function showErrorMessage(message) {
    console.error(message);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though this is a bit more code, I think it's pretty obvious what the function is doing just by reading the function names. You don't have to delve deeper in the code and increase your cognitive load to understand what the function should be doing.&lt;br&gt;
Splitting the function this way gave us the opportunity to write even better tests because we can easily focus on edge cases for any function.&lt;br&gt;
You can imagine what this method could do on a more complex function!&lt;/p&gt;

&lt;p&gt;I would argue that this would definitely be worth the time you spent splitting this function up. You will be quicker to find bugs and won't have to spend an absurd amount of time re-familiarizing yourself with the code you wrote half a year ago!&lt;/p&gt;

</description>
      <category>engineeringmonday</category>
      <category>javascript</category>
      <category>programming</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>My journey to mastering React</title>
      <dc:creator>Davor Tvorić</dc:creator>
      <pubDate>Mon, 14 Sep 2020 10:23:09 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/my-journey-to-mastering-react-82n</link>
      <guid>https://dev.to/bornfightcompany/my-journey-to-mastering-react-82n</guid>
      <description>&lt;p&gt;Let’s go back a couple of years, to a much different state in the world. When people didn’t have to stand so far apart and could freely attend social gatherings. When things in Javascript were… Kinda the same? We’re going back to the time I started learning React which, ultimately, ended abruptly. Fast forward a few years to today. I have once again started learning React, but this time I’m sticking to it. I’ll try to point out my mistakes and why it didn’t work out the first time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UrRrwvBT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.bornfight.com/wp-content/uploads/2020/08/starttingtolearnreact.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UrRrwvBT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.bornfight.com/wp-content/uploads/2020/08/starttingtolearnreact.png" alt="meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To give a bit of context, I have been working with Vue for a while now and I am still quite pleased with it. I picked Vue after I made a project in Angular 2, which didn’t really stick. Since there is a bit of a “rivalry” between Vue and React, I was apt to defend Vue instead of learning and trying to improve a cumbersome process or pattern that might have appeared in Vue. I hope this article will help to motivate you if you’re in the same state of mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  The incentive
&lt;/h2&gt;

&lt;p&gt;The first time I had a go with React was in a state where I thought Vue was a gift to humanity. Anything that was done in it was as it should be and nothing needed any changes. But since React was so popular, I thought I’d give it a go and see why so many people are developing their apps with it.&lt;br&gt;
I started out with &lt;a href="https://reactjs.org/tutorial/tutorial.html"&gt;this tutorial&lt;/a&gt;. Everything made sense, but I just didn’t like how everything clicked together. I remember thinking “why would you do this like that, in Vue you could do this...” which really isn’t the point. An interesting observation in software development is that there are always multiple ways to solve a problem. When you’re aware of that, instead of defending your solution, you can learn from someone else’s suggestion. And you can learn a lot.&lt;br&gt;
That wasn’t the case that day, obviously. After a couple of days, my will to learn React dissolved and I was left with the confirmation of my doubts. Vue is just better.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vx11Fxoz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.bornfight.com/wp-content/uploads/2020/08/outoftouch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vx11Fxoz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.bornfight.com/wp-content/uploads/2020/08/outoftouch.png" alt="meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some time passed, I’ve learned a thing or two, read a couple of books and I’ve gotten a new job at Bornfight. I was assigned to the Vue team. We had, and still do, a Vue and a React team. After a few bigger projects, we realised that it would probably be beneficial to use a single frontend framework in our Javascript team, instead of two. Knowledge sharing would be much easier and we would have a more specialized team to handle new projects. My colleagues suggested that we should use React. I agreed to that, even though it meant that I had to learn React. It made much more sense than Vue since it was easier to hire new people and the library is still more popular as it was a couple of years ago.&lt;/p&gt;

&lt;p&gt;To be honest, I was really excited about this opportunity. I have learned a lot throughout the time and I was confident that would assist me a bunch. Over the years I started to appreciate other approaches and realized that there was no rivalry between Vue and React, not really. React introduced hooks which Vue adopted in Vue 3, for instance. Both of these solutions have their pros and cons and you just have to weigh out your needs and pick your technology based on that. Armed with that knowledge and a healthy outlook on things, I started learning instead of judging. I also had a purpose and a necessity to learn React.&lt;/p&gt;

&lt;h2&gt;
  
  
  The process
&lt;/h2&gt;

&lt;p&gt;The way I went on about learning React was pretty much the same. I did the &lt;a href="https://reactjs.org/tutorial/tutorial.html"&gt;same tutorial&lt;/a&gt;, but this time I learned both React and Vue. Possessing a bit more in-depth knowledge than I did the first time helped me out a lot. If I didn’t understand something, I could easily find the terminology and search for an explanation online. At the same time, I questioned some of my own methods and used the inspiration to improve my problem-solving skills.&lt;br&gt;
After the tutorial, I wasn’t even thinking that this was nearly enough. I bought &lt;a href="https://www.udemy.com/course/react-redux/"&gt;this course&lt;/a&gt; and continued developing. To solidify my React foundations, I also watched these two tutorials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://frontendmasters.com/courses/complete-react-v5/"&gt;Complete Intro to React, v5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://frontendmasters.com/courses/intermediate-react-v2/"&gt;Intermediate React, v2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, I am more of a visual learner. I feel like I get more out of watching videos and coding aside. This doesn’t mean that I haven’t gone through the &lt;a href="https://reactjs.org/docs/getting-started.html"&gt;detailed documentation&lt;/a&gt; or read some amazing articles at &lt;a href="https://reactresources.com/"&gt;React Resources&lt;/a&gt;. I was in awe when I first saw this site and what it offered. It offers a lot of resources in one place and I wholeheartedly recommend this, as well as all of the other resources I mentioned.&lt;/p&gt;

&lt;p&gt;This was the moment I felt ready to delve in my own project. I was certain I would avoid most of the basic mistakes people make and I also had a great idea about what to make. And no, it wasn’t a to do app!&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;The way I see it, you won’t learn much if you’re prejudiced, don’t have any will to learn something new or you don’t have a goal to work towards. The first time I tried to learn React, I think I ticked all of those boxes. I was too proud to admit something I did wasn’t optimal, I really wasn’t willing to learn React and with those things combined, there really wasn’t a final goal I wanted to achieve. Nowadays, I don’t think there’s anything wrong with admitting that you could have done something better and genuinely improving where it’s necessary. I gave up too easily and I learned nothing useful.&lt;/p&gt;

&lt;p&gt;Today, I still think I am far from a master, but I believe that I learned a lot about React and frontend development in general. I am still learning, reading articles and working on React projects. I’ll probably do this for a while and I hope I’ll love doing this as much as I love doing it now. There are countless ways to improve your code and yourself and this is just one of the ways. My future steps will include working on a &lt;a href="https://github.com/ShockwaVee/books"&gt;personal project&lt;/a&gt;. It’s nothing complex, but I love reading books and this combines some of my favourite things into one. &lt;/p&gt;

&lt;p&gt;The thing I also missed the first time was someone experienced with React to help me out. I could have asked someone for an explanation on any of the numerous platforms and someone would surely help, but I was too shy to do it. Now I get the much-needed help (and PR reviews) from my colleagues here at Bornfight. I realise how invaluable this is, so if you have any questions about React, feel free to email me at &lt;a href="mailto:davor.tvoric@bornfight.com"&gt;davor.tvoric@bornfight.com&lt;/a&gt;. I can’t offer that much help, but I can try to help you figure out a solution or review a piece of code you’ve written!&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;To sum everything up, I would say that you must be willing to get your hands dirty. You can learn something by reading an article or watching a video, but the real knowledge comes from learning from your mistakes. Reading about a solution and trying to implement it yourself have a vastly different experience between them. Even if it’s something simple, I’m certain that it’s worth doing, just for the sake of doing.&lt;br&gt;
Having someone proof your ideas and nudging you in the right direction is of tremendous help.&lt;br&gt;
If you’re in a similar spot like me, have a go at the resources I mentioned before and feel free to comment on my personal project. Any bit helps and if it benefits us both, why not?&lt;/p&gt;

&lt;p&gt;Thanks for reading and stay tuned for the next post where I will make the same (simple) app in both Vue and React. I will compare the differences and show how each of them handles the same problems in their own way!&lt;/p&gt;

</description>
      <category>engineeringmonday</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Component diagram for frontend apps</title>
      <dc:creator>Davor Tvorić</dc:creator>
      <pubDate>Mon, 17 Aug 2020 09:54:40 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/component-diagram-for-frontend-apps-2037</link>
      <guid>https://dev.to/bornfightcompany/component-diagram-for-frontend-apps-2037</guid>
      <description>&lt;p&gt;Hey everyone!&lt;/p&gt;

&lt;p&gt;I've had an idea about using component diagrams in my frontend project workflow. This idea works best with frameworks that rely on components (Vue, React, Angular, Svelte...). I messed with this on a personal project and I really like the benefits it provides, but I would like to hear your opinions or experiences that I might have missed.&lt;/p&gt;

&lt;p&gt;Here's a brief example:&lt;br&gt;
Before the start of a project, but after you have some sort of a broad idea of what the project will look like, you create a diagram that looks like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzvo4tdw40cxtv6y5gzgy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzvo4tdw40cxtv6y5gzgy.png" alt="Example component diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This example shows just two components, but the idea is that every component is noted here and that it shows the relationship and the props that get passed down from a parent component.&lt;/p&gt;

&lt;p&gt;I have a feeling this would give you a much better idea of what your components will look like at the beginning of the project and keep everyone on the same page. I think it would even help to onboard new developers at a quicker rate. &lt;/p&gt;

&lt;p&gt;This would have to be stored somewhere at a repository level so it's easy to access (for developers) and it would have to be maintained throughout the project. This is where it might fail. I imagined this as a guide, so something may be implemented differently during the development stage, but the diagram must be updated with the new information, to keep it up to date. Someone might forget or feel lazy and not update it which renders the diagram useless. I haven't thought of any way to prevent this, so I was hoping someone else might have a suggestion.&lt;/p&gt;

&lt;p&gt;Have you ever done something similar? Is the diagram showing too much/little information? If you have any opinions, please share them down below!&lt;/p&gt;

</description>
      <category>engineeringmonday</category>
      <category>react</category>
      <category>discuss</category>
      <category>vue</category>
    </item>
    <item>
      <title>Improve your Javascript code in PhpStorm</title>
      <dc:creator>Davor Tvorić</dc:creator>
      <pubDate>Mon, 20 Apr 2020 09:53:39 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/improve-your-javascript-code-in-phpstorm-2ej3</link>
      <guid>https://dev.to/bornfightcompany/improve-your-javascript-code-in-phpstorm-2ej3</guid>
      <description>&lt;p&gt;Lately, I've been looking for a simple way to check the complexity of my Javascript code. In my opinion, it should prevent you from doing crazy stuff, while maintaining a level of readability.&lt;/p&gt;

&lt;p&gt;I found out that there are many ways that you could do this, but I was searching for a solution that would be simple to implement. That way I would get the grips with what really makes a difference when checking your complexity. After that, I could proceed with testing different options and having something that could be implemented on a team level.&lt;/p&gt;

&lt;p&gt;Some Google searches later, I found out about Code Inspections in PhpStorm (as well as WebStorm). It ticked all of my boxes because it was simple, didn't require any installation and had a ton of options.&lt;/p&gt;

&lt;p&gt;Now, there are a whole lot of different checks (and levels of severity) you can set, so I won't be going through them all. You can check all of those over at &lt;a href="https://www.jetbrains.com/help/phpstorm/code-inspections-in-javascript-and-typescript.html"&gt;JetBrains&lt;/a&gt;. Some of the rules might be even coverable with ESLint and/or Prettier, but I will list all of them here. It's worth noting that this isn't a final list since I have only started using this tool.&lt;/p&gt;

&lt;p&gt;To enable Code Inspection rules, you can go to Preferences/Settings-&amp;gt;Editor-&amp;gt;Inspections-&amp;gt;Javascript. You can also set it on a project or a global level.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZQIRnFoR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lmng6tdf50k201zytnu2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZQIRnFoR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lmng6tdf50k201zytnu2.png" alt="Path in preferences for Code Inspection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Assignment issues&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assignment used as condition&lt;/li&gt;
&lt;li&gt;Nested assignment&lt;/li&gt;
&lt;li&gt;Variable is assigned to itself&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Potentially confusing code constructs&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confusing sequence of '+' or '-'&lt;/li&gt;
&lt;li&gt;Magic number&lt;/li&gt;
&lt;li&gt;Nested conditional expression&lt;/li&gt;
&lt;li&gt;Overly complex arithmetic expression&lt;/li&gt;
&lt;li&gt;Overly complex boolean expression&lt;/li&gt;
&lt;li&gt;Statement with empty body&lt;/li&gt;
&lt;li&gt;Unnecessary 'block' statement&lt;/li&gt;
&lt;li&gt;Use of 'caller' property&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Validity issues&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'this' expression which references the global object&lt;/li&gt;
&lt;li&gt;Attempt to assign to const or readonly variable&lt;/li&gt;
&lt;li&gt;Expression statement which is not assignment or call&lt;/li&gt;
&lt;li&gt;Function with inconsistent returns&lt;/li&gt;
&lt;li&gt;Referencing 'arguments' outside of function&lt;/li&gt;
&lt;li&gt;Reserved word used as name&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Async code and promises&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All of the options&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Data flow&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redundant local variable&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Probable bugs&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comparison with NaN&lt;/li&gt;
&lt;li&gt;Division by zero&lt;/li&gt;
&lt;li&gt;Infinite loop statement&lt;/li&gt;
&lt;li&gt;Infinite recursion&lt;/li&gt;
&lt;li&gt;Possibly incorrect target of indexed property access&lt;/li&gt;
&lt;li&gt;Potentially invalid constructor usage&lt;/li&gt;
&lt;li&gt;Potentially invalid reference to 'this' from closure&lt;/li&gt;
&lt;li&gt;Result of object allocation ignored&lt;/li&gt;
&lt;li&gt;Suspicious usage of 'bind' with arrow function&lt;/li&gt;
&lt;li&gt;Typeof comparing with non-standard value&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Control flow issues&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'if' statement with identical branches&lt;/li&gt;
&lt;li&gt;'if' statement with too many branches&lt;/li&gt;
&lt;li&gt;Conditional expression with identical branches&lt;/li&gt;
&lt;li&gt;Constant conditional expression&lt;/li&gt;
&lt;li&gt;Duplicate condition in 'if' statement&lt;/li&gt;
&lt;li&gt;Object is 'null' or 'undefined'&lt;/li&gt;
&lt;li&gt;Redundant 'if' statement&lt;/li&gt;
&lt;li&gt;Redundant conditional expression&lt;/li&gt;
&lt;li&gt;Tail recursion&lt;/li&gt;
&lt;li&gt;All of the unecessary and unreachable rules&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Try statement issues&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All of the options&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Function metrics&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All of the options&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;General﻿&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All of the options except non-strict mode used&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;ECMAScript 6 migration aids&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All of the options&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Potentially undesirable code constructs&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'with' statement&lt;/li&gt;
&lt;li&gt;Comma expression&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that's it! It's a long list, but I think it really helps out during development. Although most of the stuff is how you usually write code, it's good not to have the mental burden of having to think about it constantly.&lt;br&gt;
Do you have any recommendations of rules or even other tools to use? I would love to see what other people are using!&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>engineeringmonday</category>
      <category>javascript</category>
      <category>phpstorm</category>
    </item>
    <item>
      <title>What happens under the hood when you declare ref() in Vue 3?</title>
      <dc:creator>Davor Tvorić</dc:creator>
      <pubDate>Mon, 23 Mar 2020 11:40:14 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/what-happens-under-the-hood-when-you-declare-ref-in-vue-3-5hda</link>
      <guid>https://dev.to/bornfightcompany/what-happens-under-the-hood-when-you-declare-ref-in-vue-3-5hda</guid>
      <description>&lt;p&gt;Over the last weekend, I've decided to take a look at Vue 3. VueMastery provided a free weekend for their courses, so it was a perfect chance to get started (although a bit too late from my side). I watched &lt;a href="https://www.vuemastery.com/courses/vue-3-reactivity/vue3-reactivity/"&gt;Vue 3 Reactivity&lt;/a&gt; and &lt;a href="https://www.vuemastery.com/courses/vue-3-essentials/why-the-composition-api"&gt;Vue 3 Essentials&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I was positively surprised, to say the least! The main reason for that is because I've never read or written such abstract code. I mostly took Vue (and other libraries) for granted, unless I specifically needed to understand something. I decided to change this for the composition API. To see how the fundamentals work was an eye-opener, I never realized such things were possible in Javascript.&lt;/p&gt;

&lt;p&gt;Learning about tracking effects, triggering them, using object accessors, proxies and more taunted me to find out even more. That's why I made my mind up on writing this article. I'll try to explain most of the things that happen in Vue 3 (following the current source code) when you declare a ref(). I think it's done in a really clever way and an opportunity to improve your understanding of the language. I'll also urge you to check out the &lt;a href="https://github.com/vuejs/vue-next/tree/master/packages/reactivity"&gt;source code&lt;/a&gt;. Doing this, you can learn so much, but achieve a deeper understanding of the library you're using!&lt;/p&gt;

&lt;p&gt;The implementation&lt;/p&gt;

&lt;p&gt;We're going to take a look at the &lt;a href="https://github.com/vuejs/vue-next/blob/master/packages/reactivity/src/ref.ts"&gt;ref.ts&lt;/a&gt; file first. I have stripped some of the type declarations that aren't that useful to us at the moment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;convert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;isObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;createRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;shallowRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;shallowRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;createRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;shallow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;shallow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;_isRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TrackOpTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shallow&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;newVal&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;TriggerOpTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;__DEV__&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newVal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, when you call ref(), the createRef function gets called. Here we have some pretty standard stuff, checking if it already is a ref and converting an object to a reactive (this will always be false since the 'shallow' argument is not passed).&lt;/p&gt;

&lt;p&gt;Now we have some pretty cool stuff! We declare an object called r with an '_isRef' property and some object accessors. By declaring a get and a set function for a single property, we can declare what happens when you're trying to get the value or update the value. By doing that, we can add our own logic, for instance, to add reactivity to our objects. As you can see, the return value is the object we created, which is why we have to call .value on a ref variable. In Vue 2, this is done with the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty"&gt;Object.defineProperty()&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our getters and setters are looking very slim, but the whole magic happens in the track() and trigger() functions. We will see how it all fits together in the &lt;a href="https://github.com/vuejs/vue-next/blob/master/packages/reactivity/src/effect.ts"&gt;effect.ts&lt;/a&gt; file. Since there is a bit more to comprehend, I'll split the two functions into their own blocks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TrackOpTypes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;shouldTrack&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;activeEffect&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;depsMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;targetMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;depsMap&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;targetMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;depsMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;dep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;depsMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;depsMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;activeEffect&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;activeEffect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;activeEffect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__DEV__&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;activeEffect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onTrack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;activeEffect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onTrack&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;activeEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;key&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is what fascinated me, which might say that I have a really low threshold of what impresses me.&lt;br&gt;
In the track() function, we pass in the target object, a tracking type and a key. From our targetMap, we get our depsMap. The targetMap is just a map of our tracked reactive objects and their depsMap (dependencies map). A depsMap contains each of the object's properties and their dependency; the exact effect that needs to get re-run when a value changes. This might be a lot to get your head around, so I'll show you a quick example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|       targetMap     |
|-----------|---------|
| health    | depsMap |
| damage    | depsMap |
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Health and damage are our objects which properties we are tracking (which makes it reactive). Now, each object has a depsMap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|    depsMap (health)    |
|------------------|-----|
| baseAmount       | dep |
| currentAmount    | dep |
| bonusAmount      | dep |
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Each of the properties is represented here and they all have a value of dep. 'dep' represents a set of functions that get run if that specific property changes. For instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;totalHealth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;health&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;baseAmount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;health&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bonusAmount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;BaseAmount and bonusAmount will have the same function (effect) written in 'dep'. If either of those change, this function will be run and 'totalHealth' will contain the right value.&lt;/p&gt;

&lt;p&gt;This is basically what happens in the track function, with the addition that it creates a new Map or Set if a depsMap or dep doesn't already exist. After I've explained how this works, I'm sad to inform you that none of this code gets executed when we just declare an instance of ref. This is because there is no effect to be tracked, so it just gets returned on the first line. But this will happen if you add a dependency to a property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TriggerOpTypes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;oldValue&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;oldTarget&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;depsMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;targetMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;depsMap&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// never been tracked&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;effects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReactiveEffect&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;computedRunners&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReactiveEffect&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;TriggerOpTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CLEAR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// collection being cleared&lt;/span&gt;
    &lt;span class="c1"&gt;// trigger all effects for target&lt;/span&gt;
    &lt;span class="nx"&gt;depsMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;addRunners&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;effects&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computedRunners&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;length&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;depsMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;length&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;addRunners&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;effects&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computedRunners&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// schedule runs for SET | ADD | DELETE&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;addRunners&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;effects&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computedRunners&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;depsMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// also run for iteration key on ADD | DELETE | Map.SET&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;TriggerOpTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ADD&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;TriggerOpTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DELETE&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;TriggerOpTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SET&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iterationKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;length&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ITERATE_KEY&lt;/span&gt;
      &lt;span class="nx"&gt;addRunners&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;effects&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computedRunners&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;depsMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iterationKey&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReactiveEffect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;scheduleRun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;__DEV__&lt;/span&gt;
        &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;oldValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;oldTarget&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Important: computed effects must be run first so that computed getters&lt;/span&gt;
  &lt;span class="c1"&gt;// can be invalidated before any normal effects that depend on them are run.&lt;/span&gt;
  &lt;span class="nx"&gt;computedRunners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;effects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that we know how targetMap, depsMap and deps are generated, it's a lot easier to understand triggers.&lt;br&gt;
If the object has been tracked, we find our depsMap from our targetMap and get the value. If you remember, depsMap's value is deps which contains all the effects for a specific property. With the addRunnders() function, we add all of the effects to the effects or computedRunners sets, depending on the fact whether they are computed or not.&lt;br&gt;
After all of that, we run each effect for our computed properties first and then for effects. This is what makes the reactivity work after you update a single property on a tracked object.&lt;/p&gt;

&lt;p&gt;And that's the basic behaviour of our refs, calling track() and trigger() when getting or setting a property. I hope it has been clear enough and that I haven't made any wrong assumptions. There is a lot to comprehend here, but the main point is that you have gotten the gist of the refs' reactivity and how it all actually works. &lt;/p&gt;

&lt;p&gt;I've pasted the links to the files I've been looking at, so you can take a closer look and see for yourself that it's not &lt;em&gt;that&lt;/em&gt; complicated. It's also a really good learning material for patterns that you might not know!&lt;/p&gt;

</description>
      <category>engineeringmonday</category>
      <category>vue</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Handling nested data in Vue with Vuex ORM</title>
      <dc:creator>Davor Tvorić</dc:creator>
      <pubDate>Mon, 24 Feb 2020 08:01:45 +0000</pubDate>
      <link>https://dev.to/bornfightcompany/handling-nested-data-in-vue-with-vuex-orm-5cp2</link>
      <guid>https://dev.to/bornfightcompany/handling-nested-data-in-vue-with-vuex-orm-5cp2</guid>
      <description>&lt;p&gt;I’ve recently started working on a fairly complex application regarding the structure and the amount of data I get from our API. A lot of the data is meant to be reused and some of them reference the same relationships. This meant that I would, most likely, get tangled up with having some of the data not properly updated. &lt;/p&gt;

&lt;p&gt;A while back, a colleague suggested to me to try out &lt;a href="https://github.com/vuex-orm/vuex-orm"&gt;Vuex ORM&lt;/a&gt;. He reasoned that it should help a lot with nested data and act as a single source of truth. Its job is to map the data you receive from the back-end, after all.&lt;br&gt;
I was convinced, so I’ve read the &lt;a href="https://vuex-orm.github.io/vuex-orm/"&gt;documentation&lt;/a&gt;, tried it out and all I can say is that it made my life a whole lot simpler! In addition to storing the data, I was amazed by how easy it is to get the specific data (and its relationships), format it and filter it by using the query builder. I also realized that a lot of these features would not be properly utilized if you had a simple application in mind. The additional complexity might not be worth it.&lt;/p&gt;

&lt;p&gt;I won’t bore you with the basics of Vuex ORM because you can read all about them in the documentation. However, I will show you how I’m currently using it and which features have proved to be really useful.&lt;/p&gt;

&lt;p&gt;The whole plugin is really simple to set up. The only additional thing I had to think about is JSON:API. It turned out that it wasn’t so difficult because the community around Vuex ORM was busy with making all sorts of additional features for Vuex ORM. I have used a &lt;a href="https://github.com/guillaumebriday/json-api-response-converter"&gt;JSON:API normalizing library that was compatible with Vuex ORM&lt;/a&gt;. I have opted out of using their Axios plugin because I needed more control over the data I was receiving. So, in the response interceptor, I added the JSON:API normalizer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;JsonApiResponseConverter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json-api-response-converter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;appAxios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
           &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/vnd.api+json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;JsonApiResponseConverter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;formattedResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That was pretty much it. Now I could go on and create my models and actually use the library.&lt;/p&gt;

&lt;p&gt;After I’ve written a few models, I realized that I was creating a non-orthogonal system. If I’ve wanted to switch some parts of the application in the future, it would prove to be a nearly impossible task. That’s why I’ve decided to separate the concerns in my application and make less of a rigid structure. This is what I came up with and what I’m currently using.&lt;/p&gt;

&lt;h2&gt;
  
  
  The folder structure
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── src/
│   ├── API/ - contains the files that handle API calls
│   ├── models/ - contains the files that define the ORM models
│   ├── repositories/ - contains the files that act like getters for the ORM
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All of this could have been written inside the ORM model, but I found out that the files tend to grow a lot and the code gets a bit messy. You will see my point in the examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;h3&gt;
  
  
  models/OfferItem.ts
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;OfferItem&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;entity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offerItem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// defines all of the fields and relationships on a model&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;([]),&lt;/span&gt;
            &lt;span class="na"&gt;offerItemType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;priceDetails&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;([]),&lt;/span&gt;
            &lt;span class="na"&gt;priceDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;offer_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="c1"&gt;// simple inverse one-to-one relationship&lt;/span&gt;
            &lt;span class="na"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;belongsTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;product_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;material_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;material&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;belongsTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ProductCatalogue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;material_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;offer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;belongsTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Offer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offer_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// all of the methods that can be done with the model&lt;/span&gt;
    &lt;span class="c1"&gt;// i.e. fetch all, search, delete, update, etc.&lt;/span&gt;
    &lt;span class="c1"&gt;// we use the API layer here, not in the components&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;getById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerItemId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;offerItem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;offerItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;OfferItemAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerItemId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertOrUpdate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;offerItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;insertOrUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;product&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;updateExisting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChecklistFieldEntry&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="nx"&gt;offerItemId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;offerItemType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;offerItem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;offerItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;OfferItemAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateExisting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nx"&gt;offerItemId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="nx"&gt;offerItemType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertOrUpdate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;offerItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;insertOrUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;product&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;material&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  api/OfferItemsAPI.ts
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OfferItem&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/models/OfferItem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;OfferItemAPI&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// makes the actual call to the back-end&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;updateExisting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerItemId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChecklistFieldEntry&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;offerItemType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offer_items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;offerItemId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;offerItemType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;offerItem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;offerItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ApiRoutes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateExisting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerItemId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;AxiosResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerItem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;updateExistingMaterial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerItemId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChecklistFieldEntry&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;offerItem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;offerItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ApiRoutes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateExisting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerItemId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;AxiosResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerItem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  repositories/OfferItemsRepository.ts
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OfferItem&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/models/OfferItem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// using the query builder, we can easily get the specific data&lt;/span&gt;
&lt;span class="c1"&gt;// we need in our components&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;OfferItemRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;getById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerItemId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;OfferItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;whereId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerItemId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;withAll&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Even with a smaller example, you can see that the complexity would only grow with having everything in just one file.&lt;/p&gt;

&lt;p&gt;The next step of this is to use it properly and keep the layers separate. The API layer is never used inside of a component, the component can only communicate with the model and the repository. &lt;/p&gt;

&lt;h2&gt;
  
  
  Concerns
&lt;/h2&gt;

&lt;p&gt;Even though this has been a great help, I have run into some issues that have been bugging me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Model interfaces
&lt;/h3&gt;

&lt;p&gt;When you define a model and want to use the properties you set it, Typescript will argue that the properties you are using do not exist. I'm assuming this has to do with the facts they are nested in the "fields" property. Not a major issue, but you would have to write an additional interface to escape the errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  json-api-response-converter
&lt;/h3&gt;

&lt;p&gt;The library suggested by Vuex ORM has some issues when handling cyclical JSON. I have chosen to use &lt;a href="https://github.com/olosegres/jsona"&gt;jsona&lt;/a&gt; instead. The switch was relatively simple because of the way the libraries handle deserialization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Even though there are some smaller nuances with the library I've run into, I would still urge you to try it out on your complex Vue projects. It's a great benefit to not worry about the data you have and just focus on the business logic of your application.&lt;/p&gt;

</description>
      <category>engineeringmonday</category>
      <category>javascript</category>
      <category>jsonapi</category>
      <category>vue</category>
    </item>
  </channel>
</rss>
