Forms
React controlled inputs require two things for every field: a value prop bound to state, and an onChange handler that calls a setter. For large forms this becomes repetitive, which is why react-hook-form exists.
Svelte’s bind:value replaces both in one directive. Write bind:value={name} and Svelte wires up the two-way binding automatically — reading the state on render and writing back on every input event. There is no onChange, no e.target.value, no setter.
For full-page form submission without JavaScript, SvelteKit form actions in +page.server.ts handle POST requests server-side — similar to Remix action functions — with progressive enhancement built in.
Controlled input vs bind:value
Section titled “Controlled input vs bind:value”function ProfileForm() { const [name, setName] = React.useState(''); const [email, setEmail] = React.useState('');
function handleSubmit(e) { e.preventDefault(); console.log({ name, email }); }
return ( <form onSubmit={handleSubmit}> <input value={name} onChange={e => setName(e.target.value)} placeholder="Name" /> <input type="email" value={email} onChange={e => setEmail(e.target.value)} placeholder="Email" /> <button type="submit">Save</button> </form> );}<script> let name = $state(''); let email = $state('');
function handleSubmit(e) { e.preventDefault(); console.log({ name, email }); }</script>
<form onsubmit={handleSubmit}> <input bind:value={name} placeholder="Name" /> <input type="email" bind:value={email} placeholder="Email" /> <button type="submit">Save</button></form>bind:value works on input, textarea, and select. For checkboxes and radio buttons, use bind:checked. There is no onChange anywhere.
React form onSubmit vs Svelte onsubmit
Section titled “React form onSubmit vs Svelte onsubmit”function LoginForm() { const [password, setPassword] = React.useState(''); const [remember, setRemember] = React.useState(false);
return ( <form onSubmit={e => { e.preventDefault(); console.log({ password, remember }); }}> <input type="password" value={password} onChange={e => setPassword(e.target.value)} /> <label> <input type="checkbox" checked={remember} onChange={e => setRemember(e.target.checked)} /> Remember me </label> <button type="submit">Log in</button> </form> );}<script> let password = $state(''); let remember = $state(false);</script>
<form onsubmit={e => { e.preventDefault(); console.log({ password, remember });}}> <input type="password" bind:value={password} /> <label> <input type="checkbox" bind:checked={remember} /> Remember me </label> <button type="submit">Log in</button></form>