ReactJS Fetch drop-in 替换此 AJAX 样板文件

ReactJS Fetch drop-in replacement for this AJAX boilerplate

背景:

以下 AJAX 代码成功运行 (ReactJS + JQuery frontend, PHP backend)。

    const data = {request_type:"load_data", start:1, end:50};

    $.ajax({
        type: "POST",
        url: "http://localhost/site/server.php",
        data: data,
        dataType: "json", 
        success: (JSobject) => {
            this.setState({arr: JSobject.arr});
        }
    });

在 Chrome 开发工具中 server.php 的 Headers 显示为“Form Data”,如下所示:

在PHP服务器后端,有这行代码:

    $request_type = $_POST["request_type"];

为了学习如何做 Fetch(到目前为止,我一直避免使用它,主要是因为我有 AJAX 运行良好的样板),我一直在尝试构建一个 drop-in 替换上面的代码。

我试过这个:

    const data = {request_type:"load_data", start:1, end:50};

    fetch("http://localhost/site/server.php", {
        method: "POST",
        body: data
    })
        .then((JSobject) => {
            this.setState({arr: JSobject.arr});
        });

但是我得到这个 PHP 错误:

Notice: Undefined index: request_type in .....server.php

并且在 Chrome 开发工具中 server.php 的 Headers 显示如下:


所以,我尝试将数据更改为 JSON.stringify(data),如下所示:

    const data = {request_type:"load_data", start:1, end:50};

    fetch("http://localhost/site/server.php", {
        method: "POST",
        body: JSON.stringify(data)
    })
        .then((JSobject) => {
            this.setState({arr: JSobject.arr});
        });

但我仍然得到完全相同的 PHP 错误:

Notice: Undefined index: request_type in .....server.php

并且在 Chrome 开发工具中 server.php 的 Headers 显示如下:


出于普遍的挫败感(虽然这毫无意义,因为我仍在使用 JQuery),我想我会使用 JQuery 的 $.param(),那肯定会工作。

所以我尝试了这个:

    const data = $.param({request_type:"load_data", start:1, end:50});

    fetch("http://localhost/site/server.php", {
        method: "POST",
        body: data
    })
        .then((JSobject) => {
            this.setState({arr: JSobject.arr});
        });

仍然得到相同的 PHP 错误

Notice: Undefined index: request_type in .....server.php

并且在 Chrome 开发工具中 server.php 的 Headers 显示如下:


我的问题:如何修改上面的 Fetch 代码,使其成为 drop-in 顶部 AJAX 代码的替代品。

我意识到水平线的使用对某些人来说可能很麻烦。您可以允许自己相信它确实可以帮助我们很多普通人了解问题中发生的事情。

为将来可能遇到此问题的其他人回答我自己的问题(也供我自己参考)。通过 this link and this link 找出答案。以下代码有效:

fetch("http://localhost/site/server.php", {
    method: "POST",
    body: JSON.stringify(data)
}).then(response => {
      return response.json();
   }).then((JSobject) => {
       this.setState({arr: JSobject.arr});
      });

我不得不更改服务器上的一些 PHP 代码。最初的 "gatekeeper" 代码是:

$_POST = array_map("trim", $_POST);

$request_type = $_POST["request_type"];

这必须被注释掉:

$_POST = array_map("trim", $_POST);   //this had to be commented out

而必须添加:

$content = trim(file_get_contents("php://input"));
$_POST = json_decode($content, true);

并且在 Chrome 开发工具中 server.php 的 Headers 显示为“Request Payload”:


我还看到了一些添加“headers”键的建议,如下所示:

fetch("http://localhost/site/server.php", {
    method: "POST",
    headers: {"Content-Type": "application/x-www-form-urlencoded",},
    body: JSON.stringify(data)
}).then(response => {
      return response.json();
   }).then((JSobject) => {
       this.setState({arr: JSobject.arr});
      });

这也有效,但在 Chrome 开发工具中 server.php 的 Headers 显示为“Form Data”:


另一种方法是将 object(待发送)包装在 JQuery 的 $.param() 中(我对此很感兴趣,因为我经常使用 $.param() 在客户端将 key-values 附加到 form.serialize(),然后再发送到服务器上的 PHP)

const data = $.param({request_type:"load_data", start:1, end:50});

fetch("http://localhost/site/server.php", {
method: "POST",
headers: {"Content-Type": "application/x-www-form-urlencoded",},
body: data
}).then(response => {
   return response.json();
     }).then((JSobject) => {
      this.setState({arr: JSobject.arr});
       });

这样做的好处是不需要更改服务器端的代码。

在 Chrome 开发工具 server.php 的 Headers 中显示为Form Data":


不使用 JQuery:

回复:之前的方法(使用$.param()),完全不用JQuery也是可以的,但是需要一些函数来链接javascript object 的 key-value 对,同时将特殊字符正确编码为 x-www-form-urlencoded(this link 解释了如何做)。

例如,而不是这个:

const data = $.param({request_type:"load_data", start:1, end:50});

...
body: data

一个人会这样做:

const data = {request_type:"load_data", start:1, end:50};

...

...
body: "request_type=load_data&start=1&end=50"