HTML FormsSubmitting
React, Next.js & Vue
Copy-paste contact forms for React, Next.js and Vue.
Formclick has no SDK to install. In a framework you either render a plain HTML form, or post JSON with fetch and keep the state in your component.
ContactForm.jsx
import { useState } from 'react';
export default function ContactForm() {
const [status, setStatus] = useState('idle'); // idle | sending | sent | error
const [error, setError] = useState('');
async function onSubmit(e) {
e.preventDefault();
setStatus('sending');
const data = Object.fromEntries(new FormData(e.currentTarget));
const res = await fetch('https://api.formclick.io/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify({ access_key: process.env.NEXT_PUBLIC_FORMCLICK_KEY, ...data }),
});
const result = await res.json();
if (result.success) {
setStatus('sent');
e.target.reset();
} else {
setStatus('error');
setError(result.message);
}
}
if (status === 'sent') return <p>Thanks! We'll be in touch soon.</p>;
return (
<form onSubmit={onSubmit}>
<input name="name" placeholder="Name" required />
<input name="email" type="email" placeholder="Email" required />
<textarea name="message" placeholder="Message" required />
<input type="checkbox" name="botcheck" style={{ display: 'none' }} tabIndex={-1} />
<button disabled={status === 'sending'}>
{status === 'sending' ? 'Sending…' : 'Send'}
</button>
{status === 'error' && <p role="alert">{error}</p>}
</form>
);
}Keeping the key in an environment variable
The access key is public, so an env variable is about convenience rather than secrecy: one key per environment, nothing hard-coded. Next.js exposes variables prefixed with NEXT_PUBLIC_; Vite uses VITE_.
NEXT_PUBLIC_FORMCLICK_KEY=YOUR_ACCESS_KEYUsing formclick.min.js in a framework
Plain HTML forms in a framework (like the Next.js example above) should load the script too. Load it once in your root layout and it enhances forms as they are rendered, including on client-side navigation.
import Script from 'next/script';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{children}
{/* Handles submit, file upload, loading state and success/error messages. */}
<Script src="https://cdn.formclick.io/formclick.min.js" strategy="afterInteractive" />
</body>
</html>
);
}Still need help? Contact support or email support@formclick.io.