React:调用最终渲染方法之前的异步调用以更新状态

时间:2016-09-28 22:59:38

标签: javascript json ajax reactjs asynchronous

背景 我试图使用React根据某些web服务的json响应来更新一些UI元素,但是因为我有很多要渲染的元素,所以我试图通过仅拉动json来减少带宽。元素的HashCode已更新。在我的应用程序的上下文中,我无法更新我的ajax调用的异步行为。只有在异步调用完成后才强制更新元素的正确方法是什么? 我意识到在WillUpdate中设置状态是错误的。

示例:

    getInitialState: function getInitialState() {
        return { hash: 0, json: {}};
    },

    //Only get the step asJSON if the hash is updated
    shouldComponentUpdate: function(nextProps, nextState) {
        return this.state.json.hash != nextState.json.hash;
    },

    tick: function(){
        this.updateHash();
    },

    updateHash: function updateHash(){
        something.getUpdateHash(function(data){
            var hashR = data.responseJSON;
            this.setState({hash: hashR});
        }.bind(this));
    },

    updateJSON: function(){
        //This is an asynchronous call
        something.getJSON(function(data){
            var stepJ = jQuery.parseJSON(data.responseJSON);
            this.setState({json: stepJ});
        }.bind(this));
    },

    componentWillMount: function(){
        this.updateJSON();
    },

    componentDidMount: function(){
        this.interval = setInterval(this.tick, 10000);
    },

   componentWillUpdate: function(nextState, nextProps){
       //Way to update json state w/o affecting state? 
   },

    render: function render() { 
       /** Only do render after updateJSON is complete **/
   }

getInitialState: function getInitialState() { return { hash: 0, json: {}}; }, //Only get the step asJSON if the hash is updated shouldComponentUpdate: function(nextProps, nextState) { return this.state.json.hash != nextState.json.hash; }, tick: function(){ this.updateHash(); }, updateHash: function updateHash(){ something.getUpdateHash(function(data){ var hashR = data.responseJSON; this.setState({hash: hashR}); }.bind(this)); }, updateJSON: function(){ //This is an asynchronous call something.getJSON(function(data){ var stepJ = jQuery.parseJSON(data.responseJSON); this.setState({json: stepJ}); }.bind(this)); }, componentWillMount: function(){ this.updateJSON(); }, componentDidMount: function(){ this.interval = setInterval(this.tick, 10000); }, componentWillUpdate: function(nextState, nextProps){ //Way to update json state w/o affecting state? }, render: function render() { /** Only do render after updateJSON is complete **/ }

2 个答案:

答案 0 :(得分:1)

如何在updateJSON

的回调中致电updateHash
updateHash: function updateHash(){
    something.getUpdateHash(function(data){
        var hashR = data.responseJSON;
        if(hashR!==this.state.hash){
            this.updateJSON(hashR)
        }
    }.bind(this));
},

updateJSON: function(hash){
    //This is an asynchronous call
    something.getJSON(function(data){
        var stepJ = jQuery.parseJSON(data.responseJSON);
        this.setState({json: stepJ,hash});
    }.bind(this));
},

答案 1 :(得分:1)

如果我理解正确,那么只有在将来发生某些操作(检查哈希)时才需要更新DOM。我发现从显示逻辑的容器中拉出那种逻辑更有帮助,并导致使用很多无状态组件,我发现这些组件更容易推理。

// The component that you are housing everything in now
// seconds would be your JSON
const ActualDisplay = ({seconds}) => <div>It has been {seconds} since started</div>

class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      seconds: 0
    }
  }
  // This is so we can mimic the future checks
  componentWillMount(){
    let seconds = this.state.seconds
    setInterval(()=>{
      this.maybeUpdate(seconds)
      seconds++
    },1000)
  };
  // This is where you say 'if my hash is different, set state'
  maybeUpdate = (seconds) =>{
    console.log(seconds)
    if(seconds % 10 === 0){
      this.setState({
        seconds
      })
    }
  };

  render() {
    // And because we are updating the state of THIS container
    // we can just say 'Hey, whatever the state is of this, pass it down
    return <ActualDisplay seconds={this.state.seconds} />
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('mount')
)