Quick start
If you know MobX, you already know mobx-form-lite. The library is just a set of stores such as TextField, BooleanField, and helper functions like isFormTouched, isFormValid that operate on those stores.
Simple profile form
Let's build a simple profile form. Run this command to install the library:
npm install mobx-form-liteThe form is going to have 2 fields - name and email. The field name must not be empty, and the field email must contain the “@” symbol. The form submit button should be disabled if the form isn’t valid:
import { observer, useLocalObservable } from 'mobx-react-lite'
import { TextField, isFormValid } from 'mobx-form-lite'
function validateName(value: string) {
if (!value) return 'Please enter name'
}
function validateEmail(value: string) {
if (!value.includes('@')) return 'Please enter a valid email'
}
export const Example = observer(() => {
const form = useLocalObservable(() => ({
name: new TextField('', { validate: validateName }),
email: new TextField('', { validate: validateEmail }),
}))
return (
<form
onSubmit={(e) => {
e.preventDefault()
alert(`Name: ${form.name.value}, Email: ${form.email.value}`)
}}
>
<InputField field={form.name} label='Name' name='name' />
<InputField field={form.email} label='Email' name='email' type='email' />
<button type='submit' disabled={!isFormValid(form)}>
Submit
</button>
</form>
)
})And your InputField may look like this:
import { TextField } from 'mobx-form-lite'
import { HTMLInputTypeAttribute } from 'react'
import { observer } from 'mobx-react-lite'
type Props = {
field: TextField<string>
label: string
id?: string
name: string
type?: HTMLInputTypeAttribute
}
const InputField = observer((props: Props) => {
const { field, name, type, id, label } = props
return (
<div>
<label htmlFor={id}>{label}</label>
<input
id={id}
name={name}
type={type}
value={field.value}
onChange={(e) => field.onChange(e.target.value)}
onBlur={field.onBlur}
/>
{field.isTouched && field.error ? <div style={{ color: 'red' }}>{field.error}</div> : null}
</div>
)
})INFO
You write a field component once to adapt it to your UI kit and then reuse it anywhere in the project. The mobx-form-lite will release ready-to-use fields for the popular UI kits in the future.
Using a separate store
If the form's store logic becomes more complicated, you can extract it into a dedicated store and use TextField as you would with any other MobX store. In the future the store can even have multiple forms.
import { makeAutoObservable, action } from 'mobx'
import { TextField } from 'mobx-form-lite'
class UserFormStore {
form = {
name: new TextField('', { validate: validateName }),
email: new TextField('', { validate: validateEmail }),
}
constructor() {
makeAutoObservable(this)
}
}And use it the same way as before:
import { useState } from 'react'
import { observer } from 'mobx-react-lite'
import { isFormValid } from 'mobx-form-lite'
export const Example = observer(() => {
// Or retrieve via React Context
const [store] = useState(() => new UserFormStore())
const { form } = store
return (
<form
onSubmit={(e) => {
e.preventDefault()
alert(`Name: ${form.name.value}, Email: ${form.email.value}`)
}}
>
<InputField field={form.name} label='Name' name='name' />
<InputField field={form.email} label='Email' name='email' type='email' />
<button type='submit' disabled={!isFormValid(form)}>
Submit
</button>
</form>
)
})What's next
You can find more examples including advanced ones: