Skip to content

The one with lifecycle

Compare
Choose a tag to compare
@SaltyAom SaltyAom released this 08 Apr 06:58

The one with lifecycle.

What's new?

  • Lifecycle
  • update()
  • onCreated()

What's changed?

  • Code golf, smaller size and faster size.
  • State typed

Lifecycle

Lifecycle is introduced to Forsteri 0.2.
When we update a state, we might wanted to perform some condition which why lifecycle is introduced.

on()

on() is like a side-effect when state mutation(s) are perfomed. You can capture the the moment and perform some additional condition.

on() is introduced to create a side-effect performed when state changed. As an addtional helpers in state object

const Counter = ({
    state: { counter },
    set,
    on
}) => {
    on(['counter'], (newState) => {
        console.log(counter, newState.counter) // 0, 1
    })

    return <button 
        onClick={() => set('counter', counter + 1)}
    >
        Increase
    </button>
}

Every time counter is changed, on function will invoked the callback with newState a complete new mutated state which you can compared with the current one.

on() receive two parameters

  • property - Array of state key you wanted to create a side-effect.
  • callback - Side-effect function you wanted to perform.

You can also performed an side-effect on every state with property of true

on(true, (newState) => {
    console.log(newState) // Perform on every state changed
})

onCreated

As the name implied, onCreated is one of the most basic lifecycle. It only occurs when the component is created and rendered.

onCreated is one of the property of registerComponent.

registerComponent({
    onCreated: ({ state: { counter }, set }) => {
        // Triggered when component is created
        doSomething()

        set('counter', counter + 1)

        return () => {
            // Clean up, triggered when component is destroyed
            doSomething().unsubscribe()
        }
    }
})

Update state

In real-world, state change very often as its designed to be. State is a variable which change often.

Let's say we create a counter. Every time we click a button, a counter is increased, but how would we do it? We use set(), a helper function to update state.

First, let's define a view and state.

import { h, registerComponent } from 'forsteri'

const state = {
        counter: 0
    },
    Counter = ({ state: { counter }, set }) => (
        <section>
            <h1>{counter}</h1>
            <button>Increase</button>
        </section>
    )

registerComponent({
    component: 'my-counter',
    view: Counter
})

Notice that we have set here, it is responsible to update state and reflect to view.

To update state, we simply need state name and it's new value:

set('counter', counter + 1)

By default state is immutable object, we can't directly update it's value. Which we have set() to update its value.

Then we attach event and invoke set().

<section>
    <h1>{counter}</h1>
    <button onClick={() => set('counter', counter + 1)}>Increase</button>
</section>

In result this is how we looks like:

import { h, registerComponent } from 'forsteri'

const state = {
        counter: 0
    },
    Counter = ({
        state: { counter },
        set
    }) => (
        <section>
            <h1>{counter}</h1>
            <button
            	onClick={() => set('counter', counter + 1)}
            >
                Increase
            </button>
        </section>
    )

registerComponent({
    component: 'my-counter',
    view: Counter
})

In action

Now every time we click the button, it's counter would increase by one.

Way to update state

As Forsteri is state concept is immutatable which couldn't directly reassign.

There's 2 type of state mutation in Forsteri. set and update

  • set - Completely rewrite a state.
  • update - Rewrite only part of state.

Set is perfectly suitable to mutate every thing except object. Using set to update and Object, you have to create a copy of an existed object then mutate only some part. Then completly rewrite a state with a mutated state. which is why update is introduced to made this simple.

update only receive part of a state object then automatically mutate and update itself.

Consider using set for a complete rewrite of state otherwise you mostly might wanted to use update.

const state = {
    myObject: {
        name: 'forsteri',
        value: 'Nice component'
    }
}

set('myObject', { value: 'Nice library' }) 
// myObject: { 
//    value: 'Nice library' 
// }
// property 'name' is missing

update('myObject', { value: 'Nice library' }) 
// myObject: { 
//    name: 'forsteri' 
//    value: 'Nice library' 
// }
// Only 'value' is changed

Typed

It's best practice to understand the structured of most used utility and how it was typed to fully acheive best possible way to ensure typed an application.

Function Component

const Card = <
    StateType extends Object,
    PropsType extends string[] as const
>(
    stateObject: State<StateType> {
        state: StateType,
        set: (
            key: keyof StateType,
            value: StateType[keyof StateType]
        ) => StateType,
        update: (
            key: keyof StateType,
            value: Partial<StateType[keyof StateType]> & Object
        ) => StateType,
        on: (
            property: true | Array<keyof StateType>, 
            callback: (newState: StateType) => void
        ) => void
    },
    props: Record<PropsType[number], string>)
) => ForsteriVNode

Register Component

registerComponent({
    component: string,           // Define component's name
    view: ForsteriComponent,     // Function component which we declared
    state?: State<StateType>,    // State
    props?: Props<PropsType>     // Props
    onCreated?: (state: State<StateType>) => () => any  // lifecycle
})

That's every concept of what's new in Forsteri 0.2.

Contains Cat GIF

Chocola clapping - Nekopara