import { createStore } from 'zustand/vanilla'
type PersonStoreState = {
person: { firstName: string; lastName: string; email: string }
}
type PersonStoreActions = {
setPerson: (
nextPerson: (
person: PersonStoreState['person'],
) => PersonStoreState['person'] | PersonStoreState['person'],
) => void
}
type PersonStore = PersonStoreState & PersonStoreActions
const personStore = createStore<PersonStore>()((set) => ({
person: {
firstName: 'Barbara',
lastName: 'Hepworth',
email: 'bhepworth@sculpture.com',
},
setPerson: (nextPerson) =>
set((state) => ({
person:
typeof nextPerson === 'function'
? nextPerson(state.person)
: nextPerson,
})),
}))
const $firstNameInput = document.getElementById(
'first-name',
) as HTMLInputElement
const $lastNameInput = document.getElementById('last-name') as HTMLInputElement
const $emailInput = document.getElementById('email') as HTMLInputElement
const $result = document.getElementById('result') as HTMLDivElement
function handleFirstNameChange(event: Event) {
personStore.getState().setPerson((person) => ({
...person,
firstName: (event.target as any).value,
}))
}
function handleLastNameChange(event: Event) {
personStore.getState().setPerson((person) => ({
...person,
lastName: (event.target as any).value,
}))
}
function handleEmailChange(event: Event) {
personStore.getState().setPerson((person) => ({
...person,
email: (event.target as any).value,
}))
}
$firstNameInput.addEventListener('input', handleFirstNameChange)
$lastNameInput.addEventListener('input', handleLastNameChange)
$emailInput.addEventListener('input', handleEmailChange)
const render: Parameters<typeof personStore.subscribe>[0] = (state) => {
$firstNameInput.value = state.person.firstName
$lastNameInput.value = state.person.lastName
$emailInput.value = state.person.email
$result.innerHTML = `${state.person.firstName} ${state.person.lastName} (${state.person.email})`
}
render(personStore.getInitialState(), personStore.getInitialState())
personStore.subscribe(render)