在AJAX调用后ReactJS重新渲染

时间:2016-07-04 10:37:55

标签: javascript jquery ajax reactjs

学习反应,虽然我了解组件的生命周期,但我不明白,虽然我的JSON调用成功但它不会呈现我最初提取的项目列表。当我向列表添加新项目时,它会进行渲染,但这需要我单击编辑按钮并添加新元素。

var InterBox = React.createClass({
    getInitialState: function(){
        return {
            "content" : [],
            "editing" : false,
            "pulled" : false
        }
    },
    componentDidMount: function(){
        var url = "http://jsonplaceholder.typicode.com/posts";
        var tempdata = this.state.content;
        $.getJSON(url, function(data){
            for (var i = 0; i < data.length; i++) {
                var element = data[i];
                tempdata.push(element.body);
                console.log(tempdata);
            }
        });
        this.setState({"content":tempdata});
        this.forceUpdate();
    },
    addContent: function(e){
        var currentContent = this.state.content;
        currentContent.push(this.refs.content.value);
        this.refs.content.value = "";
        this.setState({"content" : currentContent, "editing" : false});
        this.render();
    },
    changeMode: function(e){
        this.setState({"editing": true});
        this.render();
    },
    render: function(){
        if (this.state.editing)
            return(
                <div>
                    <h1>{this.props.title}</h1>
                    <input type="text" ref="content"/>
                    <button onClick={this.addContent}>Add</button>
                </div>
            );
        else{
            var items = [];
            for (var i = 0; i < this.state.content.length; i++) {
                var element = this.state.content[i];
                items.push(<li>{element}</li>);
            }
            return(
                <div>
                    <h1>{this.props.title}</h1>
                    <button onClick={this.changeMode}>Edit</button>
                    <ul>
                        {items}
                    </ul>
                </div>
            );
        }
    }
});
ReactDOM.render(
    <InterBox title="Hello"></InterBox>,
    document.getElementById('main')
);

这是初始输出

The Output

这应该是什么样的

enter image description here

3 个答案:

答案 0 :(得分:5)

1。)由于 $。getJSON func是 async ,因此您应该等待响应,然后在回调中调用setState。< / p>

  let {content} = this.state;
  $.getJSON(url,data=>{
         let result = data.map(e=>e.body);
         this.setState({content:[...content, ...result]}); 
   });

2。) 您不需要 forceUpdate()和render(),因为setState为您调用渲染组件

3。) 你不应该通过push()来改变你的状态。它会导致问题和错误。相反,你可以使用spread operator或concat等

//concat returns new array
let {content} = this.state;
this.setState({content:content.concat(result)}); 

//spread operator
let {content} = this.state;
this.setState({content:[...content, ...result]}); 

4。) 如果你不想在回调中使用arrow func 你应该使用bind(this),否则你将在回调中使用未定义 for setState

 let {content} = this.state;
 $.getJSON(url,function(data){
              let result = data.map(e=>e.body);
              this.setState({content:content.concat(result)}); 
         }.bind(this));

答案 1 :(得分:0)

  1. 不要手动调用渲染函数,即应该通过反应调用。 你在AJAX呼叫响应之外设置了setState。

    var InterBox = React.createClass({
        getInitialState: function(){
            return {
                "content" : [],
                "editing" : false,
                "pulled" : false
            }
        },
        componentDidMount: function(){
            var url = "http://jsonplaceholder.typicode.com/posts";
            var tempdata = this.state.content;
            $.getJSON(url, function(data){
                for (var i = 0; i < data.length; i++) {
                    var element = data[i];
                    tempdata.push(element.body);
                    console.log(tempdata);
                }
                        this.setState({"content":tempdata});
            });
    
        },
        addContent: function(e){
            var currentContent = this.state.content;
            currentContent.push(this.refs.content.value);
            this.refs.content.value = "";
            this.setState({"content" : currentContent, "editing" : false});
        },
    changeMode: function(e){
        this.setState({"editing": true});
    },
    render: function(){
        if (this.state.editing)
            return(
                <div>
                    <h1>{this.props.title}</h1>
                    <input type="text" ref="content"/>
                    <button onClick={this.addContent}>Add</button>
                </div>
            );
        else{
            var items = [];
            for (var i = 0; i < this.state.content.length; i++) {
                var element = this.state.content[i];
                items.push(<li>{element}</li>);
            }
            return(
                <div>
                    <h1>{this.props.title}</h1>
                    <button onClick={this.changeMode}>Edit</button>
                    <ul>
                        {items}
                    </ul>
                </div>
            );
        }
    }
    

    });

    ReactDOM.render(
        <InterBox title="Hello"></InterBox>,
        document.getElementById('main')
    );
    

答案 2 :(得分:0)

无需this.forceUpdate()this.render()来电。屏幕将刷新,即在render()之后由React调用this.setState()

未显示数据的原因是您在致电this.setState()后立即致电$.getJSON(),而不是getJSON()成功回调。

这应该有效:

$.getJSON(url, function(data){
    for (var i = 0; i < data.length; i++) {
        var element = data[i];
        tempdata.push(element.body);
        console.log(tempdata);
        this.setState({"content":tempdata});
    }
});