Handling state

July 31, 2019 ยท View on GitHub

The state of form elements is controlled by your app. In React parlance, these form components are "controlled components" (as opposed to uncontrolled components where the input element stores the state).

That means that your app sets the initial state and subsequent mutated states of the form component.

State flow

A state change for Checkbox follows these steps:

StepStateComponent option
1.App sets initial component stateuncheckeddefaultChecked
2.Component is renderedunchecked
3.User input (user checks input element)intermediate: checked
4.App receives intermediate stateintermediate: checkedonChange
5.App sets mutated component statecheckedchecked
6.Component is renderedchecked

Receiving component state

Option onChange is called after user input, and receives an object with the current component state. The shape of the returned object differs slightly per component.

Mithril example

Checkbox:

m(Checkbox, {
  // read state
  onChange: state => vnode.state.checked = state.checked,
  // set checked state 
  checked: vnode.state.checked
})

Text Field:

m(TextField, {
  // read state
  onChange: newState => vnode.state.value = newState.value,
  // set checked state 
  value: vnode.state.value
})

Using streams

Polythene uses streams internally to manage state - they are a lightweight and versatile tool to store state values.

import m from "mithril"
import stream from "mithril/stream"
import { Checkbox } from "polythene-mithril"

const SimpleForm = {
  oninit: vnode => {
    const checked = stream(false)
    vnode.state = {
      checked
    }
  },
  view: vnode => {
    const state = vnode.state
    const checked = state.checked()
    return m(Checkbox, {
      label: "Label",
      onChange: newState => state.checked(newState.checked),
      checked
    })
  }
}

React example

Checkbox:

<Checkbox 
  onChange={
    newState => this.setState({ checked: newState.checked })
  }
  checked={this.state.checked}
/>

Text Field:

<TextField 
  onChange={
    newState => this.setState({ value: newState.value })
  }
  value={this.state.value}
/>

Components supporting onChange