Conf42 JavaScript 2021 - Online

Pragmatic State Management in React, Angular, and Vue.js Applications

Video size:

Abstract

It is not an easy task to manage state in evolving web applications. We will talk about the different solutions when dealing with state management in React, Angular, and Vue.js apps. These frameworks and libraries have their own ways of managing state. We will talk about the similarities of these options but we will discuss in detail the major differences as well.

Careful planning is needed to help manage risks, especially when suddenly introducing state management solutions to an existing project. In most cases, this will impact the complexity level of the project which may then affect the timelines significantly. As we go through several examples using these JavaScript frameworks and libraries, we will bridge the gap between reality and expectations on what really works in real projects.

Here, we will bridge the gap between reality and expectations especially on what really works in real-life projects.

Summary

  • Joshua Arvin Lat is the chief technology officer of Nuworks Interactive Labs. He will talk about pragmatic state management in react, angular and UGS applications. He is also an AWS machine learning hero and the author of the book Machine Learning with Amazon Sagemaker Cookbook.
  • The question here is when do we use an additional state management library. As we have more components in our site, the usual challenge here is how do we make these components communicate with each other? There are so many options out there.
  • When you have a more complex setup, it will take more time to build it. If you have more developers in your team, you need to manage everyone's time. Do we want more magic or do we want less magic?
  • Don't use your real projects as a playground. Create a small pet project, or maybe create your own personal website. Use that as your pet project where you would try out these tools. Do your learning in a different environment where you can write messy code.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
Hi there, I'm Joshua Arvin Lat and I'm going to talk about pragmatic state management in react, angular and UGS applications. So in this session we will share some practical tips and techniques that I've learned over these past couple of years when dealing with these libraries and frameworks. So so before we start, I'm going to introducing myself. I am Joshua Arvin Lat. I am the chief technology officer of Nuworks Interactive Labs. We build a lot of websites, we build a lot of applications, and I'm going to use some of the things that we've learned there along with some of the things that I've learned in my previous companies. Also these we use all of these libraries and frameworks to build basic to more complex websites and applications. I'm also an AWS machine learning hero and I'm the author of the book Machine Learning with Amazon Sagemaker Cookbook. So if you would like to take a look at my book, you'll probably find there things that you need in order to get your machine learning applications working in the cloud. So yeah, feel free to check it out. However, for today we're going to talk about web application development with react, Vuejs and angular and all the other state management libraries. So let's start so let's say that we were given a project, a project that involves let's say about four developers, maybe one product managing one QA and then one DevOps person, and we are supposed to build an e commerce application. So after about maybe one to two months of planning, your team has decided CTO use these certain tech stack. And then after a bit of research also you have decided to use a state management library to further improve the overall organization and architecture of your application. So in the first couple of weeks, the team is super excited trying out these new tools because almost everyone has never used the shiny new tools, especially the state management libraries. But of course, you did some research before you got started and you did tell everyone that yeah, after reading some blog posts, a lot of people did get successful using the state management libraries. However, after two months using these different tools and libraries, you've realized that things are not working out and you initially thought that the project would be easier using these tools. However, the tools seem to be making things much harder than it's supposed to be and there's no going back because the tool is being used in different parts of your application. And if you were to refactor things again and remove the usage of these certain libraries and tools, these, it might add an additional, let's say one month CTo, two months just to get it back to a stable state. So this is probably how your team looks like after it has encountered a lot of blockers, especially if the tool is not helping you. And instead it's, yeah, like I said earlier, giving you a much harder time to get things rolling. So the question here is, and this is a really tricky question to answer, is when do we use an additional state management library? And before we answer that, let's ask ourselves what a state management library and what is state? So when you're dealing with applications, the UI, the thing that you see would always be rendered there and it's a function of the data in the state. So if, let's say that this is your value and then this is going to be your UI. So if your value changes, then the UI should update as well. As we have more components in our site, the usual challenge here is how do we make these components communicate with each other? How do we manage state? And even when we're already using react, view and angular, we do feel that after the code gets a bit messier and data is being passed through the different props and different things, we start to think about is there a better way to do this? And a lot of us would say, yeah, maybe let's use a state management library. So here are some of the options available, and of course this is not an exhaustive list, there are so many options out there. But let's say you have NGRX, you have MoBX, you have redux, recoil, viewx and more. And the question here now is when do we use an additional state management libraries to support our needs when using the libraries and frameworks that we have. So the next couple of minutes would be focused on answering that. But let's start first with this simple examples. So if we have a very simple application, these, we have one parent component and then we have two child components where these child component needs to do some sort of action or modification on child number two on a sibling. So one way to do it is for child one to communicate CTO parent to its parents and then finding a way for the parent to send that message to child number two. So this seems pretty straightforward and we can technically survive without using any sort of additional state management layer. And this is usually one of these easier examples there because yeah, the code will not be as complex and it's also something that's readable and easy to debug. So if there's something wrong with, let's say, child number one, and we need to fix it. It's easy to find everything that's connected to child number one. However, once things get a bit more complicated, and especially if our needs would involve, let's say, having a grandchild, let's say, as seen in this image here, one of the grandchildren of child one needs to talk to one of the grandchildren of child two. So if we need to cases that message or pass that event to the other grandchild, which is not directly accessible from the first grandchild, then we have to do some sort of prop drilling mechanism where grandchild passes its data to child one, goes to the parent, goes to child two, and then goes CTO the grandchild. And yeah, you're probably aware that the more levels we have here, and the more things that's happening internally, the more complex the code becomes. And instead of us being able to make the most out of this concept of being able to identify which things are interconnected or related to each other, it's using to look like some sort of a spaghetti code, especially if some of the grandchildren will not really make use of the data which the other grandchildren would need. And there are different ways to solve this. And one of the major issues that teams encounter is that these immediately jump into solutions. Especially when they encounter this prop drilling scenario, they automatically decide to use a state management library. And that's a wrong thing to do. Why? Because you can technically solve this with other solutions, which we'll see later. So what's our overall objective anyway? If we were to take a step back? Our goal is to be able to manage this mess. And whenever the team is growing, whenever we have to deal with a code base that has its size increasing every single day, and the separation of code and the functions and the different things that's happening inside start to get more blurry, then we need some way to organize things a bit, so that when we need to look for something, it's easy to find where to fix the problem. And one of the things that people are talking about when using state managing libraries is that in most cases, you're going to deal with a lot of boilerplate code. And in the beginning, when you're talking about 20 lines of code, without those additional state management libraries, people complain that, yeah, those 20 lines will become 20 lines plus ten, plus ten, plus ten, total of 50 lines. And that's just one example of this. And even for the simple things, we need to add a lot of boilerplate code, which already affects people, because they're going to put and add a lot of files, they're going to add a lot of code, which may not make sense, especially at the start when the project is still small. Of course, when the project gets bigger, you'll start to realize, okay, maybe that makes sense, but this really depends on the project. This really depends on the type of state that you're dealing with, and there are a lot of factors we need to consider. So if we were to understand what's really happening here, it's like if we're just dealing with a really small application, let's say on the left side, we have a refrigerator and we need to manage and organize things a bit where to put the vegetables, the fruits and everything inside the refrigerator. If we try to over engineer things a bit accidentally, we may end up having this sort of container system where most of these would be empty space and we would have more boilerplate code than the actual relevant code itself, which is a bad thing. And the goal here is for us to understand when's the best time to use these layers to keep things organized. So the first thing we need to do is to try solving this by making the most out of what we have first. What do we mean by that? Let's try not installing additional libraries first, because in most cases you will be surprised that these libraries and frameworks may be more than enough to get things done. I'll repeat again, in most cases we'll most likely be able to get this done with these libraries and frameworks. So view angular and react even without installing, let's say recoil, redux, Mobex, NgrX, rxgs and so on, we'll be able to manage things a bit. Because sometimes people think, okay, we need to manage redox, when in fact these libraries and frameworks already have its own internal mechanisms to get things organized and dynamic. So here are some of the things that you can use. And let's say that if you were to use use context and use effect and use ref and use state with react, you'll be able to take on the basic to medium sized projects even without using redux or other state management libraries with angular. Given that you're dealing here with a framework with a lot of things already installed there and ready for you to use, you can use a shared service instead of NgRX first. Maybe a shared service where different components are able to talk to that shared service would do the trick, especially for projects that are being converted which are getting a bit more complex but still considered medium sized. And then yeah, with a bit of dependency injection. Also, you can combine that with the different strategies inside angular to keep things organized in your angular app and then for view js. Maybe you can start first with the mentals, the foundational building blocks of Vuejs, and then yeah, try to implement also some other techniques like using a simple global store and maybe a global event bus and understanding how these things work, you would be able to organize things better. And it does not involve a lot of boilerplate code, especially yeah, in the similar examples earlier where you're just dealing with basic to medium sized applications. There are other techniques which I will not share here, so feel free to take a look because the goal here is to be able to maximize the tools first before introducing new ones. Because the moment you introduce new tools in your arsenal and in your project, all developers of that project involved in that project needed to learn these new tools as well. So the familiarity level takes time. Being able to be more familiar with these tools take time and as much as possible, try to limit the tools, especially when the other tools are not yet needed. So here we can see that if we were to use react and redux, when the project is somewhat smaller at the start, you will start to feel that, yeah, there's a lot of boilerplate code and the relevant logic code is just a piece of it. So you'll probably feel when it's best to use redox. And one of the technique that can be used here would be to use, let's say something like redux toolkit to reduce the boilerplate code. So do some research first before taking things on, because there might be newer solutions as we go along when you're using certain tools and frameworks, because that's one of the known weaknesses of using this state management libraries. What if, let's say we use Mobex to replace Redux? So for one thing, people think that redux and react are the partners when it cases to state management in react. However, that part is interchangeable and we can use other state management libraries with react. So for Mobex, for example, there's more magic when using Mobex. And of course the assumptions are a bit different here because the way it works is super, is kind of different as with redux. So there's definitely less boilerplate code. And when your team size is maybe somewhat smaller than what you have compared to when you're dealing with Redux, then maybe Mobix is for you. But of course there's more magic, things are less explicit and so on. So you have to understand the concepts here as the assumptions are different, like what I mentioned earlier. So now, one of the things which would make it easier for you to choose would be time, because time will affect everything, it will affect the budget, it will affect the launch dates, it will affect the things that you can do. And this will affect also the debugging time that you have. So what do I mean by that? When you have a more complex setup, it will take more time to build it. If you have more developers in your team, you need to manage everyone's time. So if you have a 30 man team versus a five man team, it's important to be able to manage complexity while reducing the overall time to deploy things, because it's super expensive when you're dealing with a much larger team compared to a smaller one. So if you have a smaller one and the timeline is a bit tough and you need to deploy things, let's say, next month, then doing something the elegant way may not be the right way to do things. Maybe try to do something that's somewhere there in the middle. That's why you need to be able to research first what options are available for you and what are the constraints that you have. So let's say that you're using view js already in your project, and if you want to migrate it to react, you need to take note of the skill level of your developers, also the amount of time it takes to migrate your project from view to react, and so on. And if you want to use, let's say, recoil and everyone else has used redux, then you have to also take into account the time it takes for people to learn recoil and these amount of time that you need to standardize things. Because even if you have this state management library, it will not automatically make your code cleaner. You need to be able to use those libraries properly before you can get a polished application. Another question we have to ask ourselves. Do we want more magic or do we want less magic? Let's say when you're using Mobix, a lot of magic is being done because of mobex, right? And in some cases, when we're using redux, things are more explicit. So when there's a problem, of course it's much easier to see where the but probably is, right. And when you have more members in the team, there are less assumptions to make and you can just see, okay, there's a problem with this function, or I can just probably look in these certain files, certain set of files, and just modify and tweak things a bit there to fix the problem when you're using more magic, of course, when there are issues and bugs. And when you're checking things on why it's not working, sometimes it's harder to debug and troubleshoot. So being aware of how to troubleshoot these issues is very important. And knowing the differences between the one day data binding concepts and two way data binding is crucial. Also, along with the usage of different tools, let's say the browser plugins, you need to be able to research what's available out there. And let's say there's a time travel mechanism these how can you use it to debug what's happening inside here? It's important for us to note that strong assumptions yield strong guarantees. So if we're using this certain concept, let's say immutability, if we're going to enforce certain architecture patterns in our application, then there's going to be a trade off. We're using to, let's say, have more code and more files. But when there are issues already, in some cases the issues are prevented and much more manageable. And those are some of the stronger guarantees which are results from having strong assumptions or strong rules. So when you're dealing with super complex applications, of course you needed to have this stronger rules, stronger set of rules to make things more manageable. And of course, if your application is much smaller and you are okay to have a higher level of risk, because you know that this project will probably not evolving into something larger in the future, then maybe use something that has more magic in it. Another thing to check would be the capability and experience of your entire team. Whenever there's a meeting. The usual problem these is that people think that they are masters of a certain tech stack. Let's say that they have used angular and NGRX to create a hello world application. So they create a button and then use this, it emits something and then something subscribe or something like that and it works, right? And these, they add another button and then another component changes. Because of that, they assume that they're already experts using angular and NGRX. However, when we start using and installing different things there, let's say that there's an API and then there are a lot of events happening all over the place, then that's these. You'll see that there's some sort of gap when it comes to capability and experience because your team is unable to resolve something, which is supposedly very easy when you're just using plain, angular or plain, let's say even jquery, right? So if you're trying to complexity things a bit, using a new layer then maybe it's time to step back a bit and check, do we really need these tools? And if you need these tools, do we need CTO? Make sure that we're trained first and capable of solving more complex problems so that things won't be implemented the wrong way. So there. So the goal here is for the team to make less mistakes or no mistakes, so that they'll be able to use the tools properly. One way to do this is to give an exam to your team members so that it's very easy to see if they're really capable of building a medium sized complex applications with these tech stacks, because it's easy to say, yeah, I can build something like that. But if you were to do things hands on, and if you're going to build a clone of what you're supposed to do, something that's more isolated and something that's easier to perform in, let's say 8 hours, then that would be your way to identify if your project is going to succeed with this text using this certain roster. In addition to this, it's important for us to identify and note the different types of state and why do we need to know these things. For one thing, there's a tendency of team members to put everything in the store using the state management libraries, and in most cases that's going to be overkill. There are only certain types of state that we need to put in the store, and it's not just that. We also need to know the different ways to control the state and to know where to store the state. Also, for example, in server state that's stored in the server, you will not need the more advanced and complex solutions there, especially if the operations are pretty straightforward. Let's say that you have a form and you just need to submit the form. Does it need to go through all this complex code just to send a post request to the server? And maybe you can store also the state in the router and so on. So being able to identify the different types of state would help us identify which state can be stored inside in the store of the state management libraries, for example, local UI state, you don't really need that stored in the global state then yeah, it's better if it's just there in the scope of that component. So why do we have an image of a hammer here? Because if all you have is a hammer, everything becomes a nail. And if you try to use these certain tools and text tags in all of your applications, you'll start to realize it's not going to work for all of it. If you try to read a blog post saying yeah, it works for us, this certain tooling works for us in our project, and you start copying their text app without thinking about the implications and how it would really work in your own context and application, then yeah, you'll encounter a lot of problems there. So the first step here is to check what's out there and what's available and try to select which tools are most suitable for your context for your own application. So for example, for project one and it's already using Vuejs, then yeah, just use vuejs. If it's not going to evolve into something that's super large, then Vuejs would do the trick. And maybe there's no need to use vuejs there. For project number two, you're using Vuejs there and you start to realize actually the code is getting much, much bigger. The team needs to use view x then yeah, these use viewx for that and make sure that Viewx is used properly and you're just using viewx for the state that is supposedly in, that is supposed to be in viewx because you can use both view the view way of things and the viewx way of things when dealing with state in an application. There's no need to be pure when choosing these types of things because whatever works for your team should do the trick. For project number three, let's say that your team is using react and then your team decides to use recoil instead of redux, then go for it. Just make sure that you don't change your minds midway and decide to use redux so that you have to refactor everything and start again from scratch just to realize let's use redux or mobile instead. And for project number four, maybe you decided to use angular for that. Or the client may be already be using angular for it, and then you're supposed to build on top of the existing framework then yeah, use angular. If you think that it makes sense to use NGRx or other options, then yeah, test things, but first and identify how it would affect the timeline and how it would affect the happiness of these developers and also their productivity. So this is one good example on how to take a look at it. People think that oh yeah, these moment the project becomes a bit complex, maybe somewhere around medium complexity. That's the time I need to start using the state management libraries. But like I said, in most cases you may not need it. The best way to do it is to start checking all of the features and functionalities of the library or framework that you're using. For example, angular. It has services there. By using, let's say, the angular CLI, you'll be able to get a service. And these, you can just have the different components talk to each other using a service as one example. But once things get a bit more complex and you start to realize that you need to manage how the data is being managed and how the data flows. Cto the different components these, yeah, feel free to introducing NGRX, especially on a certain complexity level where you have a single page application and a lot of components are interconnected. Other considerations we needed to take note of would be managing the performance issues, because when you're using state management libraries, it's easy to get things started when you're doing a hello world project. But when you're dealing with a real project, you will realize that some parts of your application will be slow. So when you're, let's say, rendering a certain page, you do not want to accidentally trigger certain parts of your application, and then there's a chain reaction, and then this certain component, for some reason loads really slow, or sometimes it flickers. We also need to deal with memory leaks, especially when you're dealing with components and you need to do some cleanup. It needs to be implemented properly using the library or framework of choice. We also need to take note of how to reduce the boilerplate code, and there are ways to do that, especially in my example earlier where we use redux toolkit to reduce the overall boilerplate code to speed things up a bit. Also, and also CTO. Add more CTo be more straightforward in terms of like, instead of choosing something over the other. Sometimes having a more rigid set of timelines would do the trick. And then also we need to identify antipatterns when using these differences, libraries and frameworks, because these antipatterns would be different, because these libraries and frameworks have their own ways of doing things. Finally, why do we have a picture of a playground here? Don't use your real projects as a playground. Create a small pet project, or maybe create your own personal website or something like that, and use that as your pet project where you would try out these tools. Do not experiment on the actual projects because you do not have any room for mistakes or failures there. You are not supposed to learn and apply things at the same time and expect things to be clean when it comes to implementation. As much as possible, you would do your learning in a different environment where you can write messy code without having to worry about the implications because once you need to implement things in a real project, it needed to be clean, and you need to worry about the constraints like the timeline, the budget, and the people that you work with. You do not want to introduce a new tool to a project where all the other developers in your team have no idea what you're going to introducing. So again, in summary, do not use your real projects as pet projects where you will introducing fancy new tools just to add to your resume. And that's pretty much it. Thank you again for listening to my my talk and hope you learned something new. And again, I am Joshua Arvin Lat. You've learned a few things about pragmatic state management in react, angular and UGS application. Thank you again and have a productive day ahead.
...

Joshua Arvin Lat

CTO @ NuWorks Interactive Labs

Joshua Arvin Lat's LinkedIn account Joshua Arvin Lat's twitter account



Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways