The one with lifecycle
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.