State Subscription

Advanced State Operations - Subscriptions

Introduction

In the last chapter, we learned how we can create states using the State() function and store values, get and update them.

The State.onUpdate() method is depricated and removed from previews and versions.

For advanced operations, like complete control of a stateful object, it is recommended to use the State.subscribe() method.

Filtering Values

The state.subcribe() function can be used for filter values or to avoid cuss words, or any other use cases where you might need to mutate the incoming value in the state. It is more like a pipeline before the value is finally set.

You can only mutate values for set subscriptions, other than that any other subscriptions can call the function and you will have the value in your callback, but you cannot stop a variable from "getting" a value from the state using this filtration. You can, in theory mutate the data before it was get, but it is not recommended.

Let's see how we can remove the word "Apple" with asterisk in a sentence that was stored to a state:

import { render, State, $, StateModify } from '@weblabsjs/core';
import { div, p, input } from '@weblabsjs/core/components';

function App() {
  const inp = State<string>('');

  inp.subscribe("set", (prev: string, newv: string) => {
    return StateModify<string>(newv.replace(/apple/gi, "*****"))
  })

  return div(
    p('Hello World'),
    input()
      .prop('placeholder', 'Enter text')
      .event('input', (e) => inp.set(e.target.value)),

    $(() => p(inp.get()), inp)
  );
}

render('app', App());

In the above code, you can see we subscribed to the state inp and in the callback we are getting the previous as well as the new values.

We are now returning the new data using the StateModify<type>() function that simply replaces the world apple using regular expression /apple/gi which simply means case insensitive global text to some asterisk.

Always use the StateModify<type>() function if you are mutating the value provided with the set function. This is a way for weblabs to understand that the state value needs to be mutated. Any other value except true and false would have caused no effect, making the callback function essentially useless.

If you have returned true the default value, i.e newv would have been set. If you have returned nothing, then the default value, i.e newv would have been set. If you have returned false, no set operation would have taken place.

Setting up Read Filtration

There might be some cases where you want to store data in raw format, but read them differently. Now you can add a function that can 'filter' read data without setting up custom functions.

import { $, DebugRender, State, StateModify } from '@weblabsjs/core'
import { div, input, p } from '@weblabsjs/core/components'

function App() {

    const text = State<string>("")

    text.subscribe('get', (value: string) => {
        return StateModify<string>(value.replace(/apple/ig, '*****'))
    })


    return div(
        input().prop("placeholder", "Enter text")
            .event("input", (e: any) => text.set(e.target.value)),

        $(() => p(text.get({ filter: true })), text)
    )
}

DebugRender("app", App)

This is very simillar to how we mutate the set event values, and it will only work if the option { filter: true} is passed. If filtration option is set to false, or not passed, then filtration will not work.

This was done because you do not want to permanently set the getter function to something else, and that's the whole point of subscribing to the get event.

Other subscriptions

There are other events like:

  • set:only which calls the callback function iff the value that was stored in the set was not mutated by the set subscription method.

  • set:after which calls the callback function everytime the set function is called. It is a replacement event for the .onUpdate() method.

Last updated

Was this helpful?