# Gatsby

> Um formulário Gatsby que já funciona no HTML estático antes da hidratação, aprimorado com fetch depois, mais uma Gatsby Function para envios com chave secreta.

O Gatsby renderiza cada página em HTML no build. Dê ao formulário um `action` de verdade e ele envia antes de o React hidratar, ou se o bundle não carregar; depois da hidratação, o componente envia com `fetch` e mostra o resultado no lugar.

## Envie a partir do navegador

### Passo 1: Adicione o id do formulário

`.env.production`:

```bash
GATSBY_IKIFORM_FORM_ID=frm_xxxxxxxxxxxxxxxx
```

O Gatsby só expõe ao código do navegador as variáveis que começam com `GATSBY_`, e as incorpora no build. Adicione a mesma linha em `.env.development` para o `gatsby develop`.

### Passo 2: Adicione o componente

`src/components/contact-form.js`:

```jsx
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>
  );
}
```

Renderize-o em qualquer página, por exemplo `src/pages/contact.js`, e adicione `src/pages/thanks.js` para o redirecionamento sem JavaScript. Para erros de campo e a verificação humana do SDK, estenda-o como no [guia de React](https://ikiform.com/pt-br/docs/guides/react.md#component).

## Envie a partir de uma Gatsby Function

Uma Gatsby Function pode repassar o envio com uma chave secreta, o que pula os domínios permitidos e a verificação humana. Ela só roda em hosts que suportam Gatsby Functions, como a Netlify com o adapter do Gatsby; um host puramente estático como o GitHub Pages não consegue rodá-la. Guarde `IKIFORM_FORM_ID` e uma chave secreta com o escopo `submissions:write` como `IKIFORM_SECRET_KEY`, sem o prefixo `GATSBY_`, para que nunca cheguem ao navegador.

`src/api/contact.js`:

```js
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());
}
```

O Gatsby converte corpos JSON e form-encoded em `req.body`, então a página pode enviar para `/api/contact` de qualquer forma. Todos os envios passam a compartilhar o endereço IP da sua function nos limites de taxa; veja [A partir de um servidor](https://ikiform.com/pt-br/docs/guides/server.md).

## Domínios permitidos

Isto vale para envios pelo navegador. Envios pela Gatsby Function usam uma chave secreta e pulam a verificação.

| Onde o formulário roda | Adicione em Allowed domains |
| --- | --- |
| `gatsby develop` e `gatsby serve` | `localhost`. Ele corresponde a `http://localhost:8000` e `http://localhost:9000`: o Ikiform compara só o nome do host, nunca a porta. |
| Seu domínio | `example.com`, que também cobre `www.example.com` |
| Netlify | `your-site.netlify.app`. Deploy previews (`deploy-preview-12--your-site.netlify.app`) e branch deploys (`branch--your-site.netlify.app`) não são subdomínios dele, então adicione o host exato do preview enquanto testa um. |
| Cloudflare Pages | `your-project.pages.dev`. URLs de preview como `abc123.your-project.pages.dev` são subdomínios dele, então já correspondem. |

- Nunca adicione `netlify.app` ou `pages.dev` sozinhos. Todo site naquele host corresponderia, inclusive os de outras pessoas.

## Checklist de teste

1. Rode `gatsby build` e abra `public/contact/index.html`. O `action` do formulário deve terminar no id do seu formulário, não em `undefined`.
2. Rode `gatsby serve` com `localhost` nos domínios permitidos e envie. A mensagem de agradecimento deve substituir o formulário.
3. Desative o JavaScript, recarregue e envie. Você deve ver a página de agradecimento do Ikiform localmente, ou `/thanks/` no seu domínio `https:`.
4. Se você usa a function, envie para `/api/contact` em um deploy preview e confirme que o envio aparece no Ikiform.

## Solução de problemas

| O que você vê | Por quê | Correção |
| --- | --- | --- |
| `404 not_found`, e o action termina em `/f/undefined` | A variável não tem o prefixo `GATSBY_`, ou não estava definida no build | Chame-a de `GATSBY_IKIFORM_FORM_ID` e gere o build de novo. |
| A function responde `403 forbidden` | A chave secreta é de outro workspace, foi revogada ou não tem `submissions:write` | Crie uma chave secreta com esse escopo. |
| `/api/contact` retorna `404` depois do deploy | O host só serve arquivos estáticos | Faça deploy em um host com Gatsby Functions ou use a versão para navegador. |
| Os envios chegam no filtro de spam com `origin_mismatch` | A página que enviou não está nos domínios permitidos do formulário | Adicione o host da tabela acima. Com **Reject** escolhido, os mesmos envios recebem `403 origin_not_allowed`. |

## Relacionados

- [React](https://ikiform.com/pt-br/docs/guides/react.md): Estados de carregamento, erro e sucesso.
- [A partir de um servidor](https://ikiform.com/pt-br/docs/guides/server.md): Envie com uma chave de API secreta.
- [Domínios permitidos](https://ikiform.com/pt-br/docs/spam.md#allowed-domains): Como as origens são comparadas e o que acontece quando não correspondem.
- [Erros](https://ikiform.com/pt-br/docs/errors.md): Todos os códigos de erro, com causa e correção.
