Gatsby
Un formulario de Gatsby que ya funciona en el HTML estático antes de la hidratación, mejorado con fetch después, más una Gatsby Function para envíos con una clave secreta.
Gatsby renderiza cada página a HTML en tiempo de build. Dale al formulario un action real y enviará antes de que React se hidrate, o si el bundle no carga; una vez hidratado, el componente envía con fetch y muestra el resultado en su sitio.
Envía desde el navegador
Añade el id del formulario
.env.production GATSBY_IKIFORM_FORM_ID=frm_xxxxxxxxxxxxxxxxGatsby solo expone al código del navegador las variables que empiezan con
GATSBY_, y las incrusta en tiempo de build. Añade la misma línea a.env.developmentparagatsby develop.Añade el componente
src/components/contact-form.js import * as React from "react"; const endpoint = `https://ikiform.com/f/${process.env.GATSBY_IKIFORM_FORM_ID}`; export default function ContactForm() { const [status, setStatus] = React.useState("idle"); const [message, setMessage] = React.useState(""); async function onSubmit(event) { event.preventDefault(); setStatus("sending"); try { const response = await fetch(endpoint, { method: "POST", headers: { Accept: "application/json" }, body: new FormData(event.currentTarget), }); const result = await response.json(); if (result.ok) return setStatus("sent"); setMessage(result.error.message); } catch { setMessage("Couldn't reach the server. Try again."); } setStatus("error"); } if (status === "sent") return <p>Thanks, we got it.</p>; return ( <form action={endpoint} method="post" onSubmit={onSubmit}> <label> Email <input name="email" type="email" autoComplete="email" required /> </label> <label> Message <textarea name="message" rows={5} /> </label> <input type="hidden" name="_redirect" value="https://example.com/thanks/" /> <input name="_gotcha" type="text" tabIndex={-1} autoComplete="off" hidden /> {status === "error" ? <p role="alert">{message}</p> : null} <button disabled={status === "sending"}>Send</button> </form> ); }Renderízalo desde cualquier página, por ejemplo
src/pages/contact.js, y añadesrc/pages/thanks.jspara la redirección sin JavaScript. Para errores por campo y la verificación humana del SDK, amplíalo como en la guía de React.
Envía desde una Gatsby Function
Una Gatsby Function puede reenviar los datos con una clave secreta, lo que se salta los dominios permitidos y la verificación humana. Solo funciona en hostings que admiten Gatsby Functions, como Netlify con el adaptador de Gatsby; un hosting puramente estático como GitHub Pages no puede ejecutarla. Guarda IKIFORM_FORM_ID y una clave secreta con el permiso submissions:write como IKIFORM_SECRET_KEY, sin el prefijo GATSBY_ para que nunca lleguen al navegador.
export default async function handler(req, res) {
if (req.method !== "POST") return res.status(405).end();
const response = await fetch(`https://ikiform.com/f/${process.env.IKIFORM_FORM_ID}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: `Bearer ${process.env.IKIFORM_SECRET_KEY}`,
},
body: JSON.stringify(req.body),
});
res.status(response.status).json(await response.json());
}Gatsby convierte los cuerpos JSON y form-encoded en req.body, así que la página puede enviar a /api/contact de cualquiera de las dos formas. Todos los envíos comparten entonces la dirección IP de tu función para los límites de frecuencia; consulta Desde un servidor.
Dominios permitidos
Esto aplica a los envíos desde el navegador. Los envíos desde la Gatsby Function usan una clave secreta y se saltan la comprobación.
| Dónde funciona el formulario | Añadir a Allowed domains |
|---|---|
gatsby develop y gatsby serve | localhost. Coincide con http://localhost:8000 y http://localhost:9000: Ikiform solo compara el nombre de host, nunca el puerto. |
| Tu dominio | example.com, que también cubre www.example.com |
| Netlify | your-site.netlify.app. Los deploy previews (deploy-preview-12--your-site.netlify.app) y los branch deploys (branch--your-site.netlify.app) no son subdominios suyos, así que añade el host exacto de la vista previa mientras la pruebas. |
| Cloudflare Pages | your-project.pages.dev. Las URL de vista previa como abc123.your-project.pages.dev son subdominios suyos, así que ya coinciden. |
- Nunca añadas
netlify.appnipages.devsolos. Coincidiría cualquier sitio de ese host, incluidos los de otras personas.
Lista de pruebas
- Ejecuta
gatsby buildy abrepublic/contact/index.html. Elactiondel formulario debería terminar en el id de tu formulario, no enundefined. - Ejecuta
gatsby serveconlocalhosten los dominios permitidos y envía. El mensaje de agradecimiento debería sustituir al formulario. - Desactiva JavaScript, recarga y envía. Deberías ver la página de agradecimiento de Ikiform en local, o
/thanks/en tu dominiohttps:. - Si usas la función, envía a
/api/contacten un deploy preview y confirma que el envío aparece en Ikiform.
Solución de problemas
| Qué ves | Por qué | Solución |
|---|---|---|
404 not_found, y el action termina en /f/undefined | La variable no tiene el prefijo GATSBY_, o no estaba definida en tiempo de build | Llámala GATSBY_IKIFORM_FORM_ID y vuelve a hacer el build. |
La función responde 403 forbidden | La clave secreta es de otro espacio de trabajo, está revocada o le falta submissions:write | Crea una clave secreta con ese permiso. |
/api/contact devuelve 404 después de desplegar | El hosting solo sirve archivos estáticos | Despliega en un hosting con Gatsby Functions o usa la versión del navegador. |
Los envíos llegan al filtro de spam con origin_mismatch | La página que envió no está entre los dominios permitidos del formulario | Añade el host de la tabla de arriba. Si eliges Reject, esos mismos envíos reciben 403 origin_not_allowed. |