Menú
Integración

Crear un formulario de contacto en React

React gestiona la interacción mientras un punto final publicado gestiona la entrada. Realice un seguimiento explícito de los estados pendientes, de validación, de red y de éxito, y no borre el formulario hasta que se confirme la respuesta aceptada.

Crear un formulario gratis

Un ejemplo copiable

React / JSX
// Browser-side React component
import { useState, useRef } from 'react';
export default function Contact() {
  const [etat, setEtat] = useState('');
  const [busy, setBusy] = useState(false);
  const tentative = useRef({ contenu: '', id: '' });
  async function envoyer(event) {
    event.preventDefault();
    const form = event.currentTarget;
    if (!form.reportValidity()) return;
    const data = new FormData(form);
    const fields = { name: data.get('name'), email: data.get('email'), message: data.get('message') };
    const contenu = JSON.stringify(fields);
    if (contenu !== tentative.current.contenu) tentative.current = { contenu, id: crypto.randomUUID() };
    setBusy(true); setEtat("Enviando…");
    try {
      const response = await fetch("https://littlereply.com/api/submit", {
        method: 'POST', headers: { 'Content-Type': 'application/json', 'Idempotency-Key': tentative.current.id },
        body: JSON.stringify({ form_key: "YOUR_ACCESS_KEY", fields })
      });
      const result = await response.json();
      if (!response.ok) throw new Error(response.status === 429 ? "Límite alcanzado. Vuelve a intentarlo más tarde." : "No se pudo enviar. Verifique los campos e inténtelo nuevamente.");
      setEtat("Tu mensaje fue guardado. La entrega de correo electrónico se rastrea por separado.");
    } catch (error) { setEtat(error instanceof Error ? error.message : "No se pudo enviar."); }
    finally { setBusy(false); }
  }
  return <form onSubmit={envoyer}>
    <label>Tu nombre<input name='name' autoComplete='name' required /></label>
    <label>Tu correo electrónico<input name='email' type='email' autoComplete='email' required /></label>
    <label>tu mensaje<textarea name='message' required maxLength={5000} /></label>
    <button disabled={busy}>enviar mensaje</button>
    <p role='status' aria-live='polite'>{etat}</p>
  </form>;
}

la clave YOUR_ACCESS_KEY es un marcador de posición para reemplazar con la clave pública de su formulario. El código no contiene clave de servidor ni dirección de destino.

Mantener estado recuperable

Utilice campos controlados o administrados por formulario, deshabilite el botón de envío solo mientras la solicitud esté activa y mantenga los valores cuando el servidor rechace un campo o la red falle.

Genere un identificador de intento para un envío y reutilícelo solo cuando vuelva a intentar los mismos valores. Genere un nuevo identificador después de que el visitante edite la solicitud.

Leer el contrato de respuesta.

Maneje 422 como un problema de campo o esquema, 429 como un límite de tasa o cuota y 5xx o fallas de red como reintentables solo cuando se conoce el resultado. No convierta un resultado incierto en un envío duplicado automático.

Después de 202, genera una confirmación almacenada veraz. Los resultados de integración y correo electrónico permanecen disponibles en el historial de entrega.

Mantener la configuración privada fuera del paquete

El navegador puede contener la clave de formulario público. Los destinatarios, las claves de proveedor, los tokens de administración y los secretos de conexión permanecen en el espacio de trabajo privado o en el entorno del servidor.

Pruebe la plantilla antes de crear una cuenta.

Vista previa local: los cambios permanecen en este navegador. No se envía ningún mensaje o correo electrónico.

contacto HTML

Nombre, correo electrónico y mensaje: lo esencial para iniciar una conversación.

1 / 1
LittleReply

Personalizar campos y estilos

HTML/CSS independiente
<!doctype html>
<html lang="es"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Formulario de contacto</title>
<style>form[data-littlereply]{max-width:640px;margin:2rem auto;padding:1.5rem;font:16px/1.6 system-ui,sans-serif;color:#202033;background:white;border:1px solid #e4e4ee;border-radius:16px;box-sizing:border-box}form[data-littlereply] label{display:block;margin-top:1rem;font-weight:600}form[data-littlereply] input,form[data-littlereply] textarea,form[data-littlereply] select{box-sizing:border-box;width:100%;padding:.75rem;font:inherit;border:1px solid #727285;border-radius:8px;background:white;color:#202033}form[data-littlereply] input[type=checkbox],form[data-littlereply] input[type=radio]{width:auto}form[data-littlereply] button{margin-top:1rem;padding:.8rem 1.1rem;font:inherit;font-weight:600;border:0;border-radius:8px;background:var(--form-accent,#4f46e5);color:white;cursor:pointer}form[data-littlereply] :focus-visible{outline:3px solid #f59e0b;outline-offset:3px}form[data-littlereply] button:disabled{opacity:.6}form[data-littlereply] [role=status]{min-height:1.6em}form[data-littlereply] fieldset{border:0;padding:0}form[data-littlereply] .privacy-notice{font-size:.875rem;color:#4b4b60}
form[data-littlereply]{--form-accent:#4f46e5;--form-ink:#ffffff}
form[data-littlereply] button{color:var(--form-ink)}form[data-littlereply] button[data-fq-back]{background:#eee;color:#202033}form[data-littlereply] [hidden]{display:none}</style></head><body>
<form action="https://littlereply.com/api/submit" method="POST" data-littlereply="YOUR_ACCESS_KEY" data-locale="es" data-success="Su mensaje ha sido almacenado. Responderemos pronto.">
  <input type="hidden" name="_fq_key" value="YOUR_ACCESS_KEY" />
  <input type="text" name="botcheck" tabindex="-1" autocomplete="off" style="display:none" aria-hidden="true" />

  <label for="fq_name">Tu nombre *</label>
  <input type="text" name="name" id="fq_name" required autocomplete="name" />

  <label for="fq_email">Su dirección de correo electrónico *</label>
  <input type="email" name="email" id="fq_email" required autocomplete="email" />

  <label for="fq_message">tu mensaje *</label>
  <textarea name="message" id="fq_message" required maxlength="5000" rows="5"></textarea>

  <button type="submit">enviar mi mensaje</button>
  <p role="status" aria-live="polite"></p>
</form>
<!-- Errores AJAX accesibles y reintentos sin duplicados -->
<script src="https://littlereply.com/client/v1.js" data-api="https://littlereply.com" defer></script>
</body></html>

Reemplace YOUR_ACCESS_KEY con la clave pública de su formulario. El código incluye sus estilos y una mejora AJAX; el HTML POST nativo también funciona sin JavaScript.

Fuentes

Preguntas frecuentes

¿Debería utilizar una biblioteca de formularios de React?

Es opcional. El contrato de transporte y respuesta funciona con FormData nativo o una biblioteca de formularios.

¿Cuándo debo borrar el formulario?

Después de una respuesta aceptada confirmada, nunca antes de que se conozca el resultado de la solicitud.

Del ejemplo a tu formulario

Crear un formulario gratis