Updating state from inputs in Zustand
Flat updates in Zustand go through set: pass the changed fields and the store merges them into the current state.
How it works
- Store with state and actions. The store holds
firstNameandlastNameplus one update action for each field. [1] - set merges the new fields. Each action returns only the field it changes, for example
{ firstName }. The other field stays as it was. [1] - Read values with selectors.
NameFieldsandGreetingare separate components. Both pick their values with selector functions, so typing in an input updates the greeting. [2]
Run and edit it
It runs in your browser, in a sandboxed frame that cannot see this site; the packages load from esm.sh only after you press Run.
import { create } from 'zustand'
// Create your store with state and the actions that update it
const usePersonStore = create((set) => ({
firstName: 'Ada',
lastName: 'Lovelace',
updateFirstName: (firstName) => set(() => ({ firstName: firstName })),
updateLastName: (lastName) => set(() => ({ lastName: lastName })),
}))
const label = { display: 'block', fontSize: 12, color: '#9aa0ad', marginBottom: 12 }
const input = { display: 'block', width: '100%', marginTop: 4, padding: '8px 10px', borderRadius: 8, border: '1px solid #3a3f4b', background: '#12141a', color: '#e8eaf0', fontSize: 15, boxSizing: 'border-box' }
function NameFields() {
const firstName = usePersonStore((state) => state.firstName)
const lastName = usePersonStore((state) => state.lastName)
const updateFirstName = usePersonStore((state) => state.updateFirstName)
const updateLastName = usePersonStore((state) => state.updateLastName)
return (
<div>
<label style={label}>First name
<input style={input} value={firstName} onChange={(e) => updateFirstName(e.currentTarget.value)} />
</label>
<label style={label}>Last name
<input style={input} value={lastName} onChange={(e) => updateLastName(e.currentTarget.value)} />
</label>
</div>
)
}
// A separate component reads the same store
function Greeting() {
const firstName = usePersonStore((state) => state.firstName)
const lastName = usePersonStore((state) => state.lastName)
return <h2 style={{ margin: '6px 0 0', fontSize: 24, color: '#f5b84a' }}>Hello, {firstName} {lastName}!</h2>
}
export default function App() {
return (
<div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#111', fontFamily: 'system-ui, sans-serif' }}>
<div style={{ background: '#1c1f26', color: '#e8eaf0', padding: 26, borderRadius: 14, width: 400, boxSizing: 'border-box' }}>
<NameFields />
<Greeting />
</div>
</div>
)
}
Type in either field and the greeting below updates as you type. Code written by AgentGid [1].
Type in either field and the greeting below updates as you type. Code written by AgentGid [1].Checked Oct 12, 2026: it starts without errors in Chromium with zustand 5.0.15, react 19.3.0, react-dom 19.3.0. Needs WebGL.
More Zustand examples
Creating a store in Zustand Async actions in Zustand Using a Zustand store outside components Updating nested state in Zustand
Sources
Explanations written by AgentGid from the official docs; the numbers in brackets point here. The code marked "written by AgentGid" is ours and free to copy.