DEV Community

How State Management works? Dead simple SM in Vanilla JavaScript

Vijay Pushkin on March 09, 2021

Dead simple State Management in Vanilla JavaScript It's been years now since you started using Redux, MobX or even plain React Hooks and have no id...
Collapse
 
artydev profile image
artydev • Edited

Here is an optimised version :-)

import {render, html} from 'uhtml';

const App = (function () {

  const State = {
    counter : 0
  }

  function incer () {
    State.counter += 1;
    App.redraw()
  }

  function view () {
    return html`
      <h1>${State.counter}</h1>
      <button class="counter" onclick=${incer}>INC</button>
      <input value = "not erased"/>`
  }

  function redraw () {
    render(app, view())
  }

  return { redraw }

})()

App.redraw()




Enter fullscreen mode Exit fullscreen mode

You can test it here : SSMOPT

Collapse
 
artydev profile image
artydev

And if you want to get a little further

import {render, html} from 'uhtml';


const Header = () => html`<h1>Header</h1>`
const Footer = () => html`<h1>Footer</h1>`
const Counter = (state, actions) => html`
      <h1>${state.counter}</h1>
      <button class="counter" onclick=${actions.inc}>INC</button>
      <input value = "not erased"/>`

const App = (function () {

  const State = {
    counter : 0
  }

  const Actions = {
    inc : () =>  {
      State.counter += 1;
      redraw();
    }
  }

  function view (s, a) {
    return html`
      ${Header()}
      ${Counter(s, a)}
      ${Footer()}
    `
  }

  function redraw () {
    render(app, view(State, Actions))
  }

  return { redraw }

})()

App.redraw()

Enter fullscreen mode Exit fullscreen mode

You can test it here IntroSamPattern

Collapse
 
reenaverma profile image
Reena Verma

Hi @artydev- this is really interesting. I've not heard of the uthml package before. What exactly is it used/needed for vs the original package?

Collapse
 
artydev profile image
artydev

Thank you for your post.

Here is a variation :

const App =(function () {

  const State = {
    counter : 0
  }

  function render () {
    app.innerHTML = view ();
    return App
  }

  function incer () {
    State.counter += 1;
    App
      .render()
      .setupEvents();
  }

  function view () {
    return `
      <div>Counter ${State.counter}</div>
      <button class="counter">INC</button>
    `
  }

  function setupEvents () {
  let button = 
    document
      .querySelector(".counter")
      .addEventListener("click", App.incer)
  }

  return { render, incer, setupEvents }

})();

App
  .render()
  .setupEvents();

Enter fullscreen mode Exit fullscreen mode

You can test it here : SSM

Regards

Collapse
 
vijaypushkin profile image
Vijay Pushkin

This one is great. Makes better use of functional programming.

Collapse
 
ryantheleach profile image
Ryan Leach

I don't want to come off sounding like an asshole, but is this satire?

It feels like someone whose never learnt JavaScript, and just copied react examples suddenly learnt how the language works... Unless I'm missing something fundamental.

Collapse
 
artydev profile image
artydev

Please, be comprehensive...

Collapse
 
rjegge profile image
rjegge

Are you sure you didn't want to come off sounding that way? I'm pretty sure you did.

Collapse
 
hey_yogini profile image
Yogini Bende

This is a nice explaination and it helps you understand the state management concept behind the scene. Good work 🙌

Collapse
 
sgroen profile image
Viridi • Edited

Hi Vijay Pushkin,

I know this tutorial is not about the best code but I couldn't help myself from refactoring your code ;).

<!DOCTYPE html>
<html lang="en">
<head>
    <title>State Management in Vanilla JS</title>
</head>
<body>
<div id="app"></div>
<script>
  const App = {
    state: {
      count: 0,
    },
    template() {
      return `
          <h1>Hello Vanilla JS!</h1>
          <div>
            Example of state management in Vanilla JS
          </div>
          <br />
          <h1 id="counter">${this.state.count}</h1>
          <button id="button">Increase</button>
        `;
    },
    initialize(){
      document.getElementById('app').innerHTML = this.template();
      document.getElementById("button").addEventListener("click", () => App.increment());
    },
    increment() {
      this.state.count++;
      this.updateUI();
    },
    updateUI(){
      document.getElementById('counter').textContent = this.state.count;
    }
  };
  App.initialize();
</script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jiminikiz profile image
Jiminikiz
<!DOCTYPE html>
<html lang="en">
  <head>
      <title>State Management in Vanilla JS</title>
  </head>
  <body>
    <main id="app">
    </main>
    <script id="template" type="text/template">
      <h1>{{title}}</h1>
      <h2 id="counter">{{count}}</h2>
      <button id="button">Increase</button>      
    </script>
    <script>
      const App = {
        state: {
          title: 'State Counter Example',
          count: 0,
        },
        template() {
          return template.innerHTML
            .replace('{{title}}', App.state.title)
            .replace('{{count}}', App.state.count);
        },
        initialize(){
          app.innerHTML = this.template();
          button.addEventListener("click", () => App.increment());
        },
        increment() {
          this.state.count++;
          this.render();
        },
        render(){
          counter.textContent = this.state.count;
        }
      };

      App.initialize();
    </script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode
 
artydev profile image
artydev • Edited

Hello,

here is the code of utml (877lines)

uhtml.js

You can test it here : uhtmltest

Optimized in a sense, it uses VDom Diff to update the page.

Regards

Collapse
 
snickdx profile image
Nicholas Mendez • Edited

So happy to see some framework-agnostic content. This is a great read and shows sometimes we can get by just fine with the standard web technologies.

I was really wondering why you had _App and App but your justification is brillaint.

Collapse
 
henshawsamuel profile image
Samuel Henshaw

Great insight

Collapse
 
salsferrazza profile image
Salvatore Sferrazza

Really into this, thank you for sharing! The cognitive burden of many frameworks is too high for what one gets in return.

I've found this routine to be helpful for rendering the state of arbitrary objects to the DOM. Additionally, when using standard HTML template tags, I've used another routine to populate slots (template parameters) and render the template at runtime.

Collapse
 
squashbugler profile image
John Grisham • Edited

Vanilla javascript? I've never heard of that library.

Collapse
 
chovy profile image
chovy

When's the next article which I hope will be web components leverage native shadow Dom to handle updates when state changes :)

Nice article by the way. Good starting point.

Collapse
 
saksham profile image
Saksham96

Nice Insight on state management, waiting for the upcoming article.

Collapse
 
shtep profile image
jim shtepa

Is your lastname really Pushkin? Like Alexander Sergeyevich Pushkin?

Collapse
 
vijaypushkin profile image
Vijay Pushkin

The place where I'm from, we don't have family names. So, yes both are my names!

Collapse
 
shtep profile image
jim shtepa

Understood, cool. Pushkin is perhaps the greatest person in Russian literature. I am from Kazakhstan and we happen to speak and learn russian language at school. Anyways you have a great name!

Collapse
 
paramsiddharth profile image
Param Siddharth • Edited

Wow! 😮😍🥰 What an amazing tutorial! Now I can start writing my own front-end web framework. 😏😏😂😂 Just kidding, I won't! But I've always wanted to know how to. Thank you for the article! 💕💕

Collapse
 
ankitakathuria profile image
ankitakathuria

hey what does it mean when you add redraw in curly braces i.e return {redraw}. Please someone explain