Skip to content

Using forState()

INFO

forState() is a method, used in the Template Tree.

forEach() accepts a State as an input, and it calls the provided callback function once, so you can render some DOM elements, representing the state. The callback function provides one argument - the input state.

js
x.forState(myState, (myState) => {
  // ...
})

The reactivity happens when you change the state itself - then the rendered DOM elements are removed, the callback is called again and new DOM elements are rendered.

But how to change the state? If you have the state in a variable, and you set the variable to something else, the variable is simply reassigned:

js
import { state } from 'paintor'

let myState = state(['one'])

myState = ['two']
// At this point myState lost the reference to the state
// and points to the ['two'] array

One solution is to use a sub-state, because states are recursive:

js
import { state } from 'paintor'

const myStates = state({ subState: ['one'] })

myStates.subState = ['two']

And the other solution is to use setState():

js
import { setState, state } from 'paintor'

let myState = state(['one'])

setState(myState, ['two'])

Sub-State Example

js
import { component, state } from 'paintor'

component((x) => {
  const myStates = state({ subState: {} })
  const buttons = [
    { type: 'text', value: 'Text' },
    { type: 'password', value: '123456' },
    { type: 'range', value: '25' },
    { type: 'color', value: '#0000FF' }
  ]

  for (const button of buttons) {
    x.button({
      textContent: button.type,
      onClick: () => {
        myStates.subState = button
      }
    })
  }

  x.hr()

  x.forState(myStates.subState, (subState) => {
    x.input({
      type: subState.type,
      value: subState.value,
    })
  })
}).paint('#using-forstate-1')
html
<div id="using-forstate-1"></div>
example

setState() Example

js
import { component, setState, state } from 'paintor'

component((x) => {
  const myStates = state({ subState: { type: 'text', value: 'Text' } })
  const buttons = [
    { type: 'text', value: 'Text' },
    { type: 'password', value: '123456' },
    { type: 'range', value: '25' },
    { type: 'color', value: '#0000FF' }
  ]

  for (const button of buttons) {
    x.button({
      textContent: button.type,
      onClick: () => {
        setState(myStates.subState, button)
      }
    })
  }

  x.hr()

  x.forState(myStates.subState, (subState) => {
    x.input({
      type: subState.type,
      value: subState.value,
    })
  })
}).paint('#using-forstate-2')
html
<div id="using-forstate-2"></div>
example