[Live Code Session] State Management in Web Components Explained
HTML-код
- Опубликовано: 3 июл 2024
- Hey Everyone! State management is one of those concepts that trips up a lot of people using web components. Let's make a basic counting application to illustrate the concept of sharing state between components.
Code: github.com/heyMP/hax-camp-mob...
By the end of this video you will understand:
- What is local state
- The challenge of local state between components
- How to use the platform (i.e. javascript events) to share state
- How to incorporate a central "store" to control application state
- How MobX helps us manage the store and update components
- How to use the mobx-lit element to easily update and render changes in our components
00:00 - Introduction
01:21 - Creating index.html and count-app element
05:30 - Introducing local state and adding count-toolbar
06:49 - Introducing state management conflict when adding increment count button in count-app
07:55 - Using the platform (i.e. javascript events) to share local state changes with other components
13:22 - Talk through some challenges with using only the platform to solve state management
15:05 - Refactor our statement using a central store and MobX.
21:00 - Updating count-app and count-toolbar using MobX autorun
23:00 - Debugging our refactor :)
24:10 - Explaining bug in our refactor and adding unidirectional data flow
25:05 - Disposing autorun functions
25:40 - Add reset count button to count-toolbar
27:25 - Centralizing logic by moving methods from components into the store
31:35 - Introducing action decorator in MobX
33:33 - Simplifying our code using the mobx-lit element
36:38 - Congrats, you've solved state management!
I'm coming from the React/Redux world and am doing a deep dive into web components. This video helped me wrap my head around state management with web components in exactly the way that I needed. Thanks for taking the time to record the video!
Note, anyone installing Mobx v6 will encounter issues. Anyone watching this and using Mobx v6 please make note of changes as the decorate function has been removed in v6:
Here is the modified sample code from this video, you just need to modify the store.js file:
import { observable, action, makeAutoObservable } from 'mobx';
class Store {
count = 0;
constructor() {
makeAutoObservable(this);
}
setTheme(theme){
this.theme = theme;
}
incrementCount() {
this.count = this.count + 1;
}
}
export const store = new Store();
** Note this works on "mobx": "^6.0.3" **
Again thanks for the video, I just had to review how to implement mobx in LitElement :)
Awesome session! many thanks!
This is an excellent introduction to state management, especially for people working on legacy code. I've been looking for a more structured way of introducing new complex screens on a jQuery, spaghetti internal tool, and I was stuck on how to handle state management without introducing a major framework and the full redux complexity. This video gave me more than I hoped for. Modular code with import statements, observables and data-binding, specific suggestions on where to put actions, clear design. I really like the unpkg convenience URLs, as well. Thank you for this!
I would be really happy to see some reasonable pattern to handle UI state. Not component or application state but UI. Like... for example custom context-menu can be opened from any place in the tree. It should be at very top in body tag to avoid any z-index caveats. Then on some internal actions or click outside (no modal) it should be removed from the document. And so on. This is only one example. But there are dialogs, nested dialogs, sidebars, popups, modals, panels.. etc... and all that state should be somehow managed. If element X is presented in the dom then do this, else do that... and so on. Its easy if you have parent/child relationships. Just emit custom event and done. But with siblings it is bit unclear to me. Sure, i can handle that in Redux/Mobx.. but still... really curious to learn good patterns.
really helpful, thanks
How coincidental, I've just completed a PoC experimental app with 90% the same concepts as Yours, I was about to publish a video today, and this morning RUclips popped up your video. I have some extra features in my experimental, like styling Bootstrap in the Shadow DOM and I started with plain no-Lit version to show the progression. Excellent, video.
Oh, very cool. I would love to see it!
Thank you for the video. I am new to Mobx (coming from the Redux world). Do you have any good suggestions on tutorials or best practices for setting up Mobx with a lit-element project - beyond your basic "hello world"?
Thanks Stephanie! Not that I know of actually. There are a lot of MobX + React tutorials which are really similar though. The MobX stores that you create in front-end apps are generally the same regardless of what front-end framework you use.
Thanks for the video, very helpful understanding how webcomponents and events work + adding state.
I'm a bit new to Webcomponents, but why do you have to write super.connectedCallback() in connectedCallback() ? In addition, can't you just remove the connectedCallback and instead use Lit-Elements built in lifecycle function "firstUpdated()" ?
Yeah great question. Writing super.connectedCallback() will inherit any functionality from the elements base class. So you are saying, "I want to add some functionality". If you wanted to not add but override functionality from a base class then you would not include super. It would probably be best practice to use super for most of the lifecycle callbacks.
The firstUpdated lifecycle is interesting. Lit-Element is adds those callbacks when there is an explicit need where the core custom element spec doesn't account for something. firstUpdated is called right after the shadowRoot is setup and the initial properties have been rendered. Where as ConnectedCallback is going to be called right after the element is attached to the DOM, potentially before the shadowRoot is setup. So while moving our state management wiring into the firstUpdated callback, we would potentially get a "flash of non setup values" where the web component renders the local value of the property, then wires up the store, which triggers another update. If we kept it in the connectedcallback the store value would most likely have been wired up before the template renders.
How do you select between XState and MobX for state management. Which according to you is better? Thank you for the video!
My default recommendation is always Mobx for the reason that it is, imo, the easiest state management out of the box solution. Start with Mobx if it's a small to medium sized project. State trees are awesome, but you better know the ins and outs of state management before jumping into it.
What is this lit element can we use mobx in vanilla js with simple html without this lit element.?
Do you have this code in github?
Yeah definitely! Sorry I should have included that before. github.com/heyMP/hax-camp-mobx-demo
Updated the description!
Great video, but he does jump right in. If anyone needs help getting the server set-up first, here is a little push in the right direction. ruclips.net/video/QNMt_vzmJag/видео.html
Why is there so much oposition to web components, at least not wide adoption?
Fantastic question. This could be a topic for an entire series. I believe that there are an incredible array of random reasons why that's the case; confusion between polymer vs. web components, stuck in between the framework wars, shadow dom vs virtual dom wars, shadow dom encapsulation frustration, big personalities with vested influence dominating narrative, and many more. In short though. I think it really boils down to DOM API specification; it's just flat out not sexy. React is a totally package with a nice website. Same with Angular and Vue.js. Not so with web components. That being said, open-wc.org/ is trying to change that. Hopefully they do and we can all live in harmony. :)
@@_heyMP I guess thats a gut summary you gave, makes sense