Vue.js London Live 2021
Panel discussion: State Management
So, hi, first of all, hi, I'm Vanessa. In comparison to those beautiful people next to me, this direction, I think, I'm not a Vue.js core member. I'm also not really into open source, I'm very sorry, but I started my journey with Vue.js in 2017 and have loved it ever since, I guess, how most of the people here in the conference. And one of my key experiences was as I added Vue.x, as I finally added Vue.x, that I was also being afraid to use it beforehand because I thought, oh, state management store sounds complicated. And I think I did a lot of very complicated things before I just did the simple thing of adding Vue.x. Before we hop into the discussions, I want to say hi to Kia and Eduardo. And starting maybe, Kia, with you, you can quickly introduce yourself and say hello to everybody. Okay, thank you, Vanessa. Hello, everybody. I'm Kia. I'm a Vue.js core team member and so excited to be here. So I'm hoping to have so much fun. Yeah, I hope you too. Okay. And hello, Eduardo. Hello. Well, I think I just did the talk before, but... Yes, you just introduced yourself before. So for everybody who missed it, watch the recording of the awesome talk of Eduardo beforehand. And Eduardo, so I would have my first question to you. Before we get into the detail question, I thought we start with the complicated question of them all. What is state management? State management is a strategy you use to deal with a state that is outside of components in your application. That's a big one. The clue is in the title. So everything that doesn't belong in a component, everything that goes beyond the component life, everything that... there is no rule about the features or the business the logic belong to, but it's about specifics is state that cannot be in one component. It has to be outside. So you need something to manage it. You need a way to... A strategy to manage that state, interact with it, read, write, et cetera. Would you then say that state is always something that is global or can there also be a local state? Yeah, there is a local state. Yeah, yeah. Components have local state. Makes sense. Okay. And since there is now Vue 3, if I think of Vue 2, I think state management, store, Vue 3, has something changed? And I know we saw the talk of before about Pinya, but has something changed in general since we have Vue 3 when it comes to state management in Vue? Who should answer this? Kjaer. Okay. Okay. So in terms of state management, if we include Vue 3 inside the state management, there's a new composition API. So this composition API, and more specifically, Vue 3 has this new reactivity package. And actually you can use this package outside of Vue. And this provides a basic Vue reactive system. And it does pretty much the same thing that you used to do in Vue 2. In Vue 2, you had options API. You define data property and it becomes reactive. But now you can import reactivity package independent from the Vue. And you can define many kinds of reactive objects like ref, reactive, computed and such. So that's one big new thing on the Vue. In terms of Vue X, actually there is a Vue X version 4, which is compatible with Vue 3, but it hasn't changed anything. Just a slightly difference between Vue 2 version is the installation logic, I think. But other things stays quite the same. So in terms of Vue X at the moment right now, there's no big difference from the Vue 2. In other words, you can migrate Vue X 3 to Vue X 4 pretty easily. You can just straightforward. But in terms of what coming next is PNF, it's currently created by Eduardo and that's the new thing. And also Vue X 5. These two share the very same thing, but this is the new thing coming to Vue 3 as a global state management tool. All right. We now said, I think, Pinya already 10 times. And I will ask the question for everybody who hasn't seen the talk beforehand to say in one or two, three, five sentences what it actually is. But what I would like to know, so in Vue 2, there was just Vue X for me as a go-to method to have state management. I tried, as I said in the beginning, some weird things beforehand. I actually tried to misuse the root element of Vue to add global variables there until I found out that, oh, this is not reactive. And I did a lot of prop trailing in the beginning. So there's things where you have props, props, props from grandparent to grand grandchildren, and then embed everything up again until I realized, oh, no, this works way better with Vue X. But when I start now a completely new project with Vue 3, would you go immediately for Vue X, maybe for Pinya, which we'll talk about? Or is there also different other new techniques we don't know about yet? Kjaer. Well, at the moment, if you can, I think you should start with Pinya if when you need a store because that's the future of Vue X or that's the direction where Vue is going. But also why I recommend Pinya is that it's very simple. And I think it's the simplest form of global store that Vue provides and with all the server side rendering support and dev tool support and everything out of the box. And I'm not saying other state management tool is bad options or not suited for Vue, but it's just other state management usually is much more complicated, even like Vue X4. So maybe the difficulty level is Pinya, Vue X4 and X state and other stuff. So I think for the first step, I think people should reach out to Pinya. And if they need more powerful or I should say more opinionated state management system, then they can go reach out. If they want flux architecture, you can use Vue X4. If you need more like state machine kind of state management, you go to X state or Lovatz.js. So I think the first choice should be Vue, Pinya and hopefully in the future, maybe Vue X5. I don't know, but if you go with Pinya, I think you're on the right path. That's a great answer. Okay. So we stopped dancing around the word. Eduardo, what is Pinya? Pinya is a store alternative. So it's a library for Vue. It's like Vue X is a store library. It's not flux. It's much more simpler. It's even less opinionated than Vue X, which is already not. I mean, Vue X4 and below. And it was initially an experiment that was two years ago to have something. So a store that has an API that works with TypeScript out of the box using the composition API. So it started as something for Vue 2 and today it works with both Vue 2 and Vue 3. And it was my vision of how to have a state management solution that can scale, but can scale up so it can be used for applications that grow because you can have all different stores, but it can also scale down in the way that as Kia says, it's simple. It's very simple. So you can really put it in a small application and you don't get a big overhead about it. I would even go further than Kia and say that you can even start by not using anything. If you don't have service side rendering, then you can just use a reactive object and some functions and split, as you were saying, the reactivity package. I mean, you don't import from the activity, you import from Vue if you're in a Vue application. So Pina is a store library for Vue 2 and Vue 3 with a focus on development experience. So now that it has the API for creating, defining stores is the same for Vue X5, or at least the RFC, we are pretty much aligned. I think maybe the name, the key ID, because we're passing as the first parameter, everything is the same. You could copy paste the code and have the same, just change the import and it will work. And then there are differences with Vue X5 is the plugin architecture, the hot module replacement, but probably Vue X5 will have the same. And then the testing. But I think that it would be very easy to keep something compatible, at least for the plugins. I think we need to go for an RFC. And then I will adapt Pina so that at some point, either Pina offers something on top of Vue X, either it becomes Vue X. So it doesn't have to be maintained anymore. So for very small applications, so I'm not sure if I'm the only one, but I'm using Vue JS without server-side rendering. I kind of use it as the modern jQuery at some points. I'd like to have just this plain reactive property that I use and shares local and global state with it for different components. What I thought about as I heard, okay, there's now Vue X and there's now Pina. Eduardo, are you afraid that there could be a react-like thought over that with Redux and MobX, like the team Redux and the team MobX? What could we all do to not have two teams, but just to say, okay, some people work better with Vue X and some people work better with Pina? No, because the difference between MobX and Redux, or what was the other one you said? Are fundamental. What's the term in English? They have a fundamental difference in the way you think and organize. The API is completely different. Vue X and Pina have the same API. The aim of Pina is to find a way to benefit from the composition API. And the reason Vue X is so simple, or it's aiming to be so simple, is because you don't need that much. And Kia is working on the SSR, which is one of the most complicated part, I think. The iteration part of REVs, reactive objects, that part is not used by Pina right now. I think even that part, I will be able to use the same as Vue X. If Vue X goes in a direction, it's going to be better than Pina. It's not going to be worse, right? It's either going to be as good as Pina or better. So I'm going to adapt Pina to match that. So it's not like a person who does a store with Pina has something to learn with doing Vue X5, which is not the case for MobX and Redux, because they're fundamentally different in the way you even think about it. And also, you don't really have to learn much. When you see a store defined with Vue X, Pina, state, getters, actions, it's pretty self-explanatory. If you use the function API, you're just creating a component that doesn't render anything. It's like a setup function. You just create Redux, compute it inside your watch, whatever you want. Understood. So we are looking in a bright future without wars between two teams. Yeah. Eduardo, what would you tell people if they are now in their company talking to their colleagues, having a sure fix and pitching for using from now on Pina instead of Vue X in this certain project? If someone then says, yeah, but it's something new, I don't know if they are already best practices and I think it's just like, there's one guy implementing it and what if he decides to do something else now? So it's not new per se. It's two years old. I was planning on releasing a stable today, but other things came up, so I didn't do it. The reason, so it's not new. You have much better touchscreen support. You're going to have an easier life developing with Pina than with Vue X3 and 4. And we know that. So unless you have, the only reason to not use Pina is you have an existing code base. So that's what Vue X4 exists for. It's because that way people can migrate to Vue 3 without having to change the store. So that's very important, but you can actually use both at the same time. They do not conflict. So you can do a partial migration. I've seen applications that do a partial migration. Yeah. Partial migration. So they use both. Honestly, as we say with so many things, give it a try. Just look at the dogs and try it by yourself. And when you're going to see all the things also conflicting, without you having to type anything, you're going to start enjoying the library and start wondering, OK, why didn't I start before using this thing? It also works for Vue 2, by the way. Great. So also to get the next question out of the way, as well, Vue X, as well, Pina is working for any kind of sizes for the projects, as I understood it now, from tiny applications to big e-commerce pages. So there's also not a decision like, OK, I take Vue X for big, big applications and Pina just for small ones. Yeah, no, it's the same. I don't know what you mean, what you think. I think so. One or the other. Yeah. It all depends on what you're building, really. And when we talk about state management, I think people tend to think that for large apps, we need state management. And for the small apps, we don't need state management or you shouldn't use state management. But I partially disagree with this because I agree that more the app becomes bigger, it becomes more complicated. So there's a high chance global store might be needed, but it's not 100 percent the case. And even if you have very, very small application, it could have simple global state, for example, like application config or maybe some session information like user who's logged in right now or not. So for those information, I think even if your app is so small, you still need store. And in that situation, I think PNN or BX5 and those small, simple state management gets very handy. You can just use it and you get all the benefit. And even if your app becomes so huge, if your app is maybe, let's say, like very functional app where there isn't much of a state, all you do is calculation. And even though the app is huge, there's not so many state in the application, then maybe you don't need any state management. So it really depends what kind of state management your application is requiring. And I think Vue is currently moving toward to become more simple. So currently, Vue 2, when you need global store, we need to use VueX and VueX is currently has this flux architecture. So there's a huge tech gap, right? You go to Vue local state to flux architecture. So now you have to learn flux architecture to just do super simple store management. But we're trying to lower this value for PNN and VX5. We are going to make the state management much, much simpler and easy to use, but not necessarily we're saying that flux architecture is bad or anything. It's just flux architecture is more opinionated, it has more rules, it has certain ways to use the store, and it might be best fit for your project and maybe not. But the key is you have to choose for your project, right? What kind of management for state management you need. And so I think it's matter of the choice. And we're trying to add a simpler choice in between going to the full flux architecture to simple store management. And I think it's going to make this store ecosystem much, the learning curves and everything much linear, I think, for the Vue 3. So moving on from the decision, everybody out there, use what you like, try out both of them. And also let us know on Twitter and everywhere else what you will go for. And since we're now talking about, Ikea, what you just said about sometimes very small applications need state management and sometimes bigger ones might not need it at all. Do you differentiate between UI state and data business logic state? Like if you fetch something from endpoints, do you store it in a different place when your UI logic like, OK, it's loading, it's clicked, it's shown, it's user logged in, et cetera? Well, I do differentiate the data and UI state, but I think it's sometimes hard to differentiate within the store. For example, I tend to like manage all the UI state within Vue component. So for example, there is some global UI component, for example, like snack bar shown on the left slide bottom on the window, like notification stuff. And those things like global UI, because the notification happens and no matter what you do on the UI, it has to stay there. So you can't really put this state on the component, right? You need to have this state on the store. In that sense, some UI state has to go into store sometimes. But other than that, most of the time, I always try to put UI state on the component and never put them in Vuex or store unless it's absolutely necessary. And for the data, because I'm also Vuex ORM, I usually put all the data, for example, like users or posts or any kind of data into store, because usually those data comes from the server side, right? What you call the API and you get the data from the server. And when you think about it, the server is global state, right? You don't know what you're going to get until you hit the API. So for me, it really makes sense to store that data to the global store, because it is global state, I mean, on the server side state. But I think it's all down to your preference. But that's what I do often with my own project. Eduardo, would you like something to add to the question? I agree with the UI state. I can do the same. Sometimes in very specific cases, you go out of the component, but as much as possible inside the components. API calls depends on the application. It means that some API calls, you can cache them and use a local cache. So you can do a stale while we validate things to make the application look as if it's really fast. I mean, or as if you have the old data immediately and you request again. So it's very smooth. But very often I just do the components for simple apps. And then if I have bigger traffic for all the things, I do add a cache layer and usually that cache layer. So there are multiple layers of cache. Cache is a really complicated topic. So you have also the server cache, which is way more important than the client side cache, but you can also use some clients that cache to improve the user experience. And I think that I always start outside of the store if I can, unless I need to use that state right away in multiple places or multiple pages. User, for example. Okay. So next question from real projects out there. If you have a component and you get something from the store there, if it's VX, Pinyin, or composable, whatever, and then you have some couple of child components, which also need one object of the store, would you rather in each child component access the store to get the same global object again? Or would you again then use a property to pass this object down to have a component, a child component that doesn't know that there is a store that exists here you already have? I see you answering. Very, very good question. And I really don't have a straight answer to this. I would love to hear what Eduardo thinks about this and how you do it in your project. But usually I prefer to fetch all the store data on the page component. So on the top level component and pass down those data to the child component as a props. But sometimes you might want to access store from the child component. And for example, when you're building a dashboard page, and you have many different kinds of data shown in the dashboard. And in this kind of case, if you fetch all the data on the parent component, then the parent component becomes really huge because this component has to fetch all the data for its own child component. So in these kinds of cases, it's much simpler to create child component that fetches its own global state. And by the way, it goes to exactly the same to the API coding problem. Should child component call API or the parent component call API and pass down the props? I think it's the exact same problem. But I still don't know the answer. I prefer to pass down all the props, but I'm still exercising whether it's a good idea to access those global state on the child component or not. I really don't know. What do you think, Eduardo? I think that most, like 80% of the applications, they do a few, like one, two API calls. And you do that at the page level. You can have other very complex applications, but that's not even 20%. That's like 1% of the application or 5% of the applications. And usually they optimize their API a lot. So you can do a lot of API calls and then you do those API calls in a more localized fashion. So you go into the child component. I usually go in my applications, I don't have that complexity, I think, of doing that many API requests. So I do one at the page level. I think it's way easier to handle. And if I can pass it as a prop, I pass it as a prop. So I don't even need that store. I avoid doing what I've seen called as prop drilling. So basically I don't like to create an artificial prop in a component just to pass it down to another component. I don't create a prop in a component if you don't use that prop, the component. In Vue 3 and with the composition API, you have an easier access to inject provide, but I rather avoid them for most cases. It's more I rather use it for UI state and components. Like an interacting, for example, a tab component, maybe that, but not for data, not for the things that you fetch from the API. And if you already have complex data and have a very complex application, for example, you might have maps overlap or things that overlap with maps, maybe you have multiple, it could be seen as multiple mini applications running together and interacting with each other. Then the store is probably easier to have the store than using a provide or having multiple props or doing the fetching from the children component. And the good point about having the data on the store is that you can actually ask the children to fetch also, the children to fetch is not as much as a big deal. Not having a store compared to only using that saying, okay, I can only do fetching in my pages. When you don't have a store, it's usually a bigger deal, but if you have a store, it's easier to allow yourself to do the fetching from different places, not only just the page component. It's always, it depends the answer anyway, but most of the cases. But that was a good point, having a store makes it easier to access the data across the component. I mean, that's the point of store, but that's one big advantage over passing, stringing down the props, I think. Yeah. Yeah. What I like is this idea of if you just pass a prop through, but you don't even use this prop in this middle component is a good rule to see, okay, maybe there is a new tree that opens in this tree of components where it makes sense again to access a store again and live there in your own world. What I completely switching the topic now, there's something called Vuex ORM and I'm not sure if it's known by everybody. So Pia, what is this framework? When do I need this? What does it do for me? Okay, so Vuex ORM is as name suggests, it gives a ORM like API access to store. So if you ever use like Lalabel or Lubion Rails, they all have active records or Lalabel has Eloquent. So they have ORM object creation mappers. So you can do things like user.find and you're passing the ID and you get the ID from a user from database. And I wanted to do the pretty much same thing on the front end because I couldn't stand the idea of having duplicated data inside store. For example, you're fetching, let's say you are trying to fetch post data, blog post data from the server. And maybe the post has also field and also is a user object, right? And maybe the post has a comments and maybe comments has also as well, and also is also a user object, right? So when you fetch these kind of nested JSON tree, there's a good chance you have duplicated data everywhere. So you have same user, but in a multiple place. If you store this data in the store directly, they're going to be three different user, but actually those are the same users. And if you want to update this, it's going to be really hard, right? Because you have to look into every single record and find out if those had the same ID or not. By using VxOrm, what it's going to do, it's going to deduplicate all the duplicated data and it's going to distract all the entities from those nested tree and store those data into the Vuex like database. So if you say posts having comments, having users in the, through VxOrm, the outcome inside the Vuex store will be posts, users, and comments separately. And when fetching the data, you can query those data as if you're using like ordinary ORM, like say you want to fetch all the comments with users or all the comments with its parent post. So you can control the fetching and stuff. And the most importantly, if you update one user object, all of the user object that referencing that user is going to update it. So for example, in that blog post, if you change the name of the user on any comment, then that user displayed on the page will, all the user's name is going to be updated. So that's what I wanted to achieve with VxOrm. It's quite complicated, but if your app is using like lots of relationships, if your app has lots of models and relationships and complicated stuff, then I would say it could be a good choice for your project. Yeah. The description also reminded me somehow like Xstate. So also something that sounds super complicated, but if you need it, you need it. And then it is pretty, pretty cool. I also talked once to the author of Xstate and he said, yeah, it's kind of complicated. You know, you have to sit down for one weekend and learn it. In what kind of weird world are we living that someone says it's complicated. You have to sit down one week and to learn it. So unfortunately we are out of time now. I want to thank both of you for your time and your knowledge. If there's anything, I will just tell the audience now to write you on Twitter for every follow up question and of course follow us here on Discord and join us for the after party later for all of the other questions. So thank you again for your time, Kier and Eduardo. Thank you Vanessa.