使用React.js进行简单的Ajax请求

8
我正在尝试在react.js中展示来自ajax请求的任何数据,但目前没有成功。 它正在尝试从测试Web API中拉取数据,已安装JQuery,尽管不是必需的,我已经查看了其他替代方案,但是到目前为止难以实现。 对于请求,我尝试使用两种方式来绑定数据:通过“this”和使用Jquery的“append”方法,但两者均无法工作。其他所有内容都可以呈现,并且控制台没有输出任何错误信息。 我正努力实现一个通用函数,可以轻松移植到react-native上,但即使在这个JQuery实现中也被卡住了。
var url = 'https://demo2697834.mockable.io/movies';

//main logic
var GetStuff= React.createClass({

    getInitialState: function() {
      return {
        entries: []
      };
    },

    componentDidMount: function() {
        $.ajax({
          url: 'https://demo2697834.mockable.io/movies',
          dataType: 'json',
          cache: false,
          success: function(data) {
            this.setState({entries: data});
            $('.test').append(data);
          }.bind(this),
          error: function(xhr, status, err) {
            console.error(this.props.url, status, err.toString());
          }.bind(this)
        });
      },

    render: function() {
      return (
        <div>{this.state.entries}</div>
      );
    }
});

//markup
<body style={MainStyles.alldivs}>
    <Header />
    <GetStuff/>
    <div class='test'></div>
    {this.props.children}
    <Footer />
</body>

更新 1

我改变了属性以适应记录声明,但没有任何变化。我尝试传入 props URL 参数,但也没有变化。我还删除了老式的 JQuery append,我正在百分之百地尝试使用 React,可惜这不是一个容易的转型过渡。

我需要在服务器配置中更改任何内容吗?我正在使用 Express?

更新 2

似乎 componentDidMount 函数根本没有调用,为了避免混淆,我将发布我的全部代码。

import React from 'react';
import ReactDom from 'react-dom';
import $ from "min-jquery";
import Header from './header';
import Footer from './footer';
//AJAX request
var GetStuff= React.createClass({
    getInitialState: function() {
      return {
        entries: []
      };
    },
    componentDidMount: function() {
        $.ajax({
          url: 'https://demo2697834.mockable.io/movies',
          dataType: 'json',
          cache: false,
          success: function(data) {
            this.setState({entries: data});
            console.log('success');
          }.bind(this),
          error: function(xhr, status, err) {
            console.error(this.props.url, status, err.toString());
            console.log('fail');
          }.bind(this)
        });
      },
    render: function() {
      return (
        <div> HERE: 
          {this.state.entries}
        </div>
      );
    }
});


// Stylesheet stuff is here, not important for this post.

//Render
var MasterLayout = React.createClass({ 
    render: function(){
        return(
            <html lang="en">
            <head>
                <title>{this.props.name}</title>
            </head>
            <body style={MainStyles.alldivs}>
                <Header />
                <GetStuff />
                {this.props.children}
                <Footer />
            </body>
            </html>
        )   
    }
});


// no idea if this is the correct setup, again docs are lacking on the real use of this.

    if(typeof window !== 'undefined') {
        ReactDom.reder(<MasterLayout />, document.getElementByID("content"));
    }
    module.exports = MasterLayout;

1
在您的 AJAX 回调函数和渲染方法中,您引用了 this.state.data,但在 getInitialState 中,您使用 entries 而不是 data 来启动状态。在成功回调中使用 this.setState({entries: data}); 并在渲染中调用 this.state.entries - Matthew Herbst
2
此外,你没有考虑React的思维方式。在React中,$('.test').append(data);这样的代码是没有用武之地的。你不应该手动更改DOM。移除test div,只需使用GetStuff中已有的渲染即可。 - Matthew Herbst
@MatthewHerbst 我理解你的逻辑,但是这还需要一个陡峭的学习曲线,文档似乎有点跳跃。非常感谢你迄今为止的帮助。我会尝试用React完成所有工作,并掌握它的逻辑。 - Paddy
你的 ReactDOM.render 函数在哪里呢? - omarjmh
@JordanHendrix 我在我的应用程序中没有调用它,我认为Express提供的路由功能会解决这个问题。 - Paddy
2个回答

4

从我所看到的,您没有加载任何URL,试试这样:

url: this.props.url,

您没有指定任何名为url的属性,只是在文件顶部分配了一个名为url的变量。

因此,您可以添加以下内容:

<GetStuff url="https://demo2697834.mockable.io/movies" />

我注意到您想将此函数迁移到react-native。我建议不要使用ajax,而应该使用fetch方法...它与ajax类似,并且是react native默认使用的方法。https://facebook.github.io/react-native/docs/network.html 您的请求应该如下所示:
fetch(this.props.url, {
  method: 'GET',
  headers: {
    'Accept': 'application/json',
  },
}).then (function (response) {return response.json()})
  .then(function (json) {/* Here is your json */})
  .catch(function (error) {/*Handle error*/});

编辑:

嗯……看起来你无法访问这些属性。在componentWillMount里试着console.log this.props。但我认为我知道this.props.urlajax函数中无法工作背后的原因。

this. inside the ajax function refers to the ajax this, and not the react this.

您可以将此绑定到您的ajax函数,或将this.props.url分配给ajax函数外部的变量(这是我会做的)。例如:

componentDidMount: function() {
        var url = this.props.url;
        $.ajax({
            url: url,

顺便提一下,有更多细节可以参考这个问题:React教程:为什么在ajax调用中绑定this

编辑2:

我注意到您正在使用纯React而没有使用TypeScript或Redux等架构。建议您考虑使用Babel与ES6Redux(它处理应用程序状态的所有内容,这是必须的!它是Flux实现)。

我已经有一段时间没有使用过纯React了,您可能需要设置propTypes,然后在getInitialState函数中分配props。

propTypes: {
    url: React.PropTypes.string,
},
getInitialState: function() {
    return {
        url: this.props.url,
    };
}

你可以通过this.state.url来访问url的值。

感谢提醒关于fetch的问题。尝试使用props声明,但是没有成功。为了暂时消除错误,我只是将其更改为url:'https://demo2697834.mockable.io/movies'。 - Paddy
@Paddy - 检查我的更新...我相信我已经找到了原因。ajax函数内部的this指的是ajax对象,而不是React对象。 - James111
改了一下,但是还没有成功。我知道这肯定是一个很小的问题,可能只是一些棘手的配置问题。不过我得说,React 这样做让我有些惊讶,我不明白为什么他们要重新发明轮子并且让它变得更难。 - Paddy

0
这是我的工作示例代码。 请在您的代码中正确参考.bind(this)中的语法。
<div id="element"></div>
<script type="text/jsx">

 var JavaEEWSTest = React.createClass({
                getInitialState: function () {
                    return {text: ''};
                },
                componentDidMount: function(){
                    $.ajax({
                        url: "http://localhost:8080/RestWeb/rest/city"
                    }).then(function(data) {
                        console.log(data.City.city);
                        this.setState({text: data.City.city});
                    }.bind(this))
                },
                render: function() {
                    return <div>Response - {this.state.text}</div>;
                }
            });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接