React Example
Complete React examples with rut.ts.
Simple RUT Input Component
import { useState } from 'react'
import { format, validate } from 'rut.ts'
export function RutInput() {
const [rut, setRut] = useState('')
const [isValid, setIsValid] = useState(false)
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const formatted = format(e.target.value, { incremental: true })
setRut(formatted)
setIsValid(validate(formatted))
}
return (
<div>
<input
type="text"
value={rut}
onChange={handleChange}
placeholder="12.345.678-5"
className={isValid ? 'valid' : 'invalid'}
/>
{!isValid && rut && (
<span className="error">Invalid RUT</span>
)}
</div>
)
}Controlled Component with Validation
import { useState, useEffect } from 'react'
import { format, validate, clean } from 'rut.ts'
interface RutInputProps {
value?: string
onChange?: (cleanedRut: string) => void
onValidChange?: (isValid: boolean) => void
strictMode?: boolean
}
export function RutInput({
value = '',
onChange,
onValidChange,
strictMode = false
}: RutInputProps) {
const [displayValue, setDisplayValue] = useState('')
const [error, setError] = useState<string | null>(null)
useEffect(() => {
if (value) {
const formatted = format(value, {
incremental: true,
throwOnError: false
})
if (formatted) setDisplayValue(formatted)
}
}, [value])
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const input = e.target.value
// Format incrementally
const formatted = format(input, { incremental: true })
setDisplayValue(formatted)
// Validate
const isValid = validate(formatted, { strict: strictMode })
if (isValid) {
setError(null)
const cleaned = clean(formatted)
onChange?.(cleaned)
onValidChange?.(true)
} else {
setError('RUT inválido')
onValidChange?.(false)
}
}
return (
<div className="rut-input">
<input
type="text"
value={displayValue}
onChange={handleChange}
placeholder="12.345.678-5"
className={error ? 'error' : ''}
/>
{error && <span className="error-message">{error}</span>}
</div>
)
}Form with Multiple Fields
import { useState } from 'react'
import { validate, clean, format } from 'rut.ts'
interface UserForm {
name: string
rut: string
email: string
}
export function UserRegistration() {
const [form, setForm] = useState<UserForm>({
name: '',
rut: '',
email: ''
})
const [errors, setErrors] = useState<Partial<UserForm>>({})
const handleRutChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const formatted = format(e.target.value, { incremental: true })
setForm(prev => ({ ...prev, rut: formatted }))
// Clear error if valid
if (validate(formatted)) {
setErrors(prev => ({ ...prev, rut: undefined }))
}
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
// Validate RUT
if (!validate(form.rut)) {
setErrors(prev => ({ ...prev, rut: 'RUT inválido' }))
return
}
// Clean RUT for API
const cleanedRut = clean(form.rut)
// Submit
await fetch('/api/users', {
method: 'POST',
body: JSON.stringify({ ...form, rut: cleanedRut })
})
}
return (
<form onSubmit={handleSubmit}>
<div>
<label>Name:</label>
<input
value={form.name}
onChange={(e) => setForm(prev => ({ ...prev, name: e.target.value }))}
/>
</div>
<div>
<label>RUT:</label>
<input
value={form.rut}
onChange={handleRutChange}
placeholder="12.345.678-5"
/>
{errors.rut && <span className="error">{errors.rut}</span>}
</div>
<div>
<label>Email:</label>
<input
type="email"
value={form.email}
onChange={(e) => setForm(prev => ({ ...prev, email: e.target.value }))}
/>
</div>
<button type="submit">Register</button>
</form>
)
}Display Formatted RUT
import { format } from 'rut.ts'
interface RutDisplayProps {
rut: string
withDots?: boolean
}
export function RutDisplay({ rut, withDots = true }: RutDisplayProps) {
const formatted = format(rut, {
dots: withDots,
throwOnError: false
})
if (!formatted) {
return <span className="error">Invalid RUT</span>
}
return <span className="rut">{formatted}</span>
}
// Usage
<RutDisplay rut="123456785" /> // '12.345.678-5'
<RutDisplay rut="123456785" withDots={false} /> // '12345678-5'Searchable RUT Table
import { useState, useMemo } from 'react'
import { clean, format, isRutLike } from 'rut.ts'
interface User {
id: number
name: string
rut: string
}
export function UserTable({ users }: { users: User[] }) {
const [search, setSearch] = useState('')
const filteredUsers = useMemo(() => {
if (!search) return users
// Clean search term for comparison
const searchCleaned = clean(search, { throwOnError: false })
if (!searchCleaned) return users
return users.filter(user => {
const userCleaned = clean(user.rut, { throwOnError: false })
return userCleaned?.includes(searchCleaned)
})
}, [users, search])
return (
<div>
<input
type="text"
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search by RUT"
/>
<table>
<thead>
<tr>
<th>Name</th>
<th>RUT</th>
</tr>
</thead>
<tbody>
{filteredUsers.map(user => (
<tr key={user.id}>
<td>{user.name}</td>
<td>{format(user.rut)}</td>
</tr>
))}
</tbody>
</table>
</div>
)
}Last updated on