使用 React 将表单发布到 API

Posted

技术标签:

【中文标题】使用 React 将表单发布到 API【英文标题】:POST a form to an API with React 【发布时间】:2019-06-14 06:57:53 【问题描述】:

我在我的 Gatsby (gatsbyjs.org) 网站上为 cmets 使用 Staticman (staticman.net)。

我一直在使用带有 method="POST"action="https://api.staticman.net/..." 参数的经典 html 表单,因为这是 Staticman 所期望的 (docs)。

但我想让它更“反应”,我已将表单操作更改为 handleSumbit() 函数:

handleSubmit(event) 
  event.preventDefault()
  fetch("https://api.staticman.net/...", 
    method: "POST",
    body: event.target,
  )

我觉得这不起作用,因为 API 需要 HTTP POST request,内容类型为 application/x-www-form-urlencoded,而我的 event.target 是一个包含大量 React 信息的表单。

如何使我的fetch() 请求看起来与提交的 HTTP POST 表单完全一样?

【问题讨论】:

Staticman 的维护者建议用户在github.com/eduardoboucas/staticman/issues/… 启动他/她自己的API 实例。 【参考方案1】:

我会使用 query-string 包之类的东西从您的组件状态重建该 POST 数据。不确定 staticman 的具体细节,但我认为您的反应组件状态中有表单值,因此您可以执行以下操作:

handleSubmit = (event) => 
  event.preventDefault()
  fetch("https://api.staticman.net/...", 
    method: "POST",
    body: queryString.stringify(
      this.state.username,
      this.state.subject
    )
  )

【讨论】:

感谢您提供有关查询字符串的提示!我最终找到了一种手动(通过 JSON)将 FormData 转换为查询字符串的方法。不完美,但它正在工作:)【参考方案2】:

经过一些研究,我找到了一个解决方案。这是我的handleSubmit 函数:

handleSubmit = async (event) => 
  event.preventDefault()

  // extract form data
  const formdata = new FormData(event.target)

  // convert FormData to json object
  // SOURCE: https://***.com/a/46774073
  const json = 
  formdata.forEach(function(value, prop)
    json[prop] = value
  )

  // convert json to urlencoded query string
  // SOURCE: https://***.com/a/37562814 (comments)
  const formBody = Object.keys(json).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(json[key])).join('&')

  // POST the request to Staticman's API endpoint
  const response = await fetch("https://dev.staticman.net/v3/entry/github/robinmetral/eaudepoisson/master/comments", 
    method: "POST",
    headers: "Content-Type": "application/x-www-form-urlencoded",
    body: formBody,
  )
    .then(response => 
      // reset form
      document.getElementById("comment-form").reset()
      // display success message
      document.getElementById("success").style.display = "block"
    )
    .catch(error => 
      console.log(error)
      document.getElementById("failure").style.display = "block"
    )

这就是它的作用:

    它将提交的数据提取为FormData 对象 它将 FormData 转换为 JSON 对象,使用 snippet found on SO 它将 JSON 转换为预期的 application/x-www-form-urlencoded 内容类型或“查询字符串”,使用 another SO snippet 它将请求发送到 API 端点,捕获错误并显示成功消息

这可能不是唯一的解决方案,如果您发现我可以改进的地方,请在 cmets 或 send me a PR 告诉我!

【讨论】:

以上是关于使用 React 将表单发布到 API的主要内容,如果未能解决你的问题,请参考以下文章

无法将多部分表单数据从 React 正确发送到 Express Js

将表单从客户端发布到 AWS API 网关功能时如何修复 CORS 错误?

带有 ReactJS 的 Django 表单

React Hooks(useEffect) 表单子任务

如何在 redux 中使用 axios 库将数据发布到 API 服务器

在 react redux saga 中处理同步