即使数据没有改变,我可以用setState强制重新渲染吗?我的GUI不会更新

时间:2017-05-17 03:06:21

标签: reactjs redux react-redux normalizr

所以我现在遇到的问题是第一次点击,我的GUI重新渲染。但是在第二次点击时,它不会重新渲染。我相信这是因为我没有更新“graphicLayers”的状态,我的渲染通过“graphicLayers.map”进行绑定。无论如何,这是我的理论(即使它适用于第一次点击?但不是第二次点击或之后的任何事情)

我尝试强制使用iconLayers的setState更新,但它似乎不起作用..就像这样

let graphicLayersCopy = Object.assign([], this.state.graphicLayers);
this.setState({graphicLayers: graphicLayersCopy});

但那不起作用。我通过调试器知道它正确设置数据,如果我刷新(它保存状态并重新加载状态),则GUI会正确呈现。

无论如何我可以强制重新渲染一个变量,即使它没有改变值也是如此?

构造

constructor(props, context) {
    super(props, context);

    this.state = {
      graphicLayers: [id1, id2, id3],
      graphicLayersById: {
        id1: { ... },
        id2: { ... },
        id3: { ... }
      }

    this.addLayerClick = this.addLayerClick.bind(this);
};

呈现

render() {
    return (        
    <div>
      {this.state.graphicLayers.map((id) =>
        <GraphicLayer addLayerClick={this.addLayerClick.bind(this)} />
      )}
    </div>
    );
   }

addLayerClick

addLayerClick() {
  ... change some property in graphicLayersById dictionary ...
  self.setState({ graphicLayersById: newDataHere });
}
编辑:嘿伙计们,所以我发现问题在我的最后,而且这里没有完全显示。

所以我的addLayerClick()实际上调用了另一个正在侦听调用的函数,并在其中设置了状态。这很奇怪,因为setState在回调函数中被调用,但我通过将setState放入addLayerClick()本身来使它工作..仍然不知道为什么这不起作用但我会至少赞成你们所有人

listenFunction(){

let self = this;

this.firebaseWrapper.storage.on('graphicLayersById', function (save) {
  if (save) {
    self.setState({ graphicLayersById: save });  // FOR SOME REASON THIS DOESN'T UPDATE THE GUI THE 2nd CLICK.  The data is correct though and I see it going here on a breakpoint, but GUI won't update unless i setState in the actual button
  }
  else {
    self.setState({ graphicLayersById: undefined });
  }
});

}

3 个答案:

答案 0 :(得分:3)

addLayerClick()中,您只需更新graphicLayersById,但渲染取决于 graphicLayers 。您还应该更新graphicLayers中的addLayerClick()州。

addLayerClick() {
  this.setState({
    graphicLayers: ...
    graphicLayersById: ....
  });
}

另一方面,您不应该绑定render()内的方法,因为这会在每个渲染上创建一个全新的函数(并且可能会影响性能)。而不是

<GraphicLayer addLayerClick={this.addLayerClick.bind(this)} />

DO

<GraphicLayer addLayerClick={this.addLayerClick} />

并在您的构造函数中保留绑定(以您已有的方式)。

答案 1 :(得分:2)

实际上,您已将addLayerClick()功能绑定到组件,因此您可以使用this代替self

您应该像这样修改您的代码:(大约有2个更改)

constructor(props, context) {
    super(props, context);

    this.state = {
      graphicLayers: [id1, id2, id3],
      graphicLayersById: {
        id1: { ... },
        id2: { ... },
        id3: { ... }
      }
    // don't need to bind here anymore, since you bind it in the click
    //this.addLayerClick = this.addLayerClick.bind(this);
};

addLayerClick() {
  //... change some property in graphicLayersById dictionary ...
  // just use 'this' here
  this.setState({ graphicLayersById: newDataHere });

  // the below line is NOT recommended, which is force the component to update
  // this.forceUpdate(); // this line will update the component even though there's no change 
}

如果这还不行,请在此处发布如何处理子组件中的onCLick函数,并发布一些错误(如果有的话),谢谢

答案 2 :(得分:2)

希望这两种可能的方式能够重新审视你的观点

this.setState({graphicLayersById: newDataHere} , ()=>{
console.log(this.state.graphicLayersById);
});

OR

var update = require('react-addons-update');
    var graphicLayers = update(this.state, {
            graphicLayersById: {$set: newDataHere}
        });
        this.setState(graphicLayers);