Reflux connectFilter 仍在向所有监听组件发送更新
Reflux connectFilter still sending updates to all listening components
我正在使用 Reflux.connectFilter mixin 让一堆 Graph 组件监听我的 GraphStore 中的变化。使用过滤器,它们应该仅在 GraphStore 的图形数组中与其 ID 匹配的元素发生更改(或 added/removed)时才重新呈现。但是,当我更新数组的单个元素时,比如通过设置名称变量,我仍然看到所有正在侦听的图形都重新呈现。我做错了什么吗?
GraphStore
var Reflux = require('reflux');
var GraphActions = require('./graphActions').GraphActions;
var GraphStore = Reflux.createStore({
listenables: [GraphActions],
init: function() {
this.graphs = [];
this.metricMetaData = {};
},
onAddGraph: function(graphId, name) { // Called only by the Dashboard component that is a parent to all Graphs
this.graphs.push(
{
id: graphId,
name: ""
}
);
this.updateGraphs();
},
onSetName: function(graphId, name) { // Called only by the Dashboard component that is a parent to all Graphs
for(var i = 0, gl = this.graphs.length; i < gl; ++i) {
if(this.graphs[i].id === graphId) {
this.graphs[i].name = name;
this.updateGraphs();
return;
}
}
},
...
updateGraphs: function() {
this.trigger(this.graphs); // This is the only place in the store where trigger is called
},
getInitialState: function() {
return this.graphs;
}
});
module.exports = {GraphStore: GraphStore};
图表
/** @jsx React.DOM */
var React = require('react');
var Reflux = require('reflux');
var GraphActions = require('./graphActions').GraphActions;
var GraphStore = require('./graphStore').GraphStore;
var Graph = React.createClass({
mixins: [Reflux.connectFilter(GraphStore, "graph", function(graphs) {
return graphs.filter(function(graph) {
return graph.id === this.props.id;
}.bind(this))[0];
})],
propTypes: {
id: React.PropTypes.string.isRequired
},
...
render: function() {
if(typeof this.state.graph === "undefined") {
return (<div>The graph has not been created in the store yet</div>);
} else {
return (<div>Graph name: {this.state.graph.name}</div>);
}
}
};
module.exports = {Graph: Graph};
仪表板
/** @jsx React.DOM */
var React = require('react');
var Graph = require('./graph').graph;
var GraphActions = require('./graphActions').GraphActions;
var UUID = require('uuid');
var Dashboard = React.createClass({
propTypes: {
numGraphs: React.PropTypes.int.isRequired
},
...
render: function() {
var graphs = [];
for(var i = 0; i < this.props.numGraphs; ++i) {
var currId = UUID.v4();
GraphActions.addGraph(currId, "");
graphs.push(<Graph id={currId} />);
}
return (<div>{graphs}</div>);
}
};
module.exports = {Dashboard: Dashboard};
我没用过 Reflux,但我认为这里的问题是你所有的 Graph
实例都在监听 GraphStore
,一旦那个商店发送一个事件,所有组件实例将收到该事件。他们会过滤掉他们不感兴趣的数据,但 Reflux 仍然会在所有实例上调用 setState
,触发它们重新渲染。如果过滤函数的结果与之前相同,Reflux 不会(据我所知)短路重新渲染。
要将它短路并避免在取回相同数据时重新渲染,您需要在组件上实现 shouldComponentUpdate
方法并将新状态与旧状态进行比较,并且 return 如果相同则为假。
一种流行的方法是将 [1] Immutable.js 与 [2] PureRenderMixin 一起使用,后者会为您短路。
[1] https://github.com/facebook/immutable-js
[2]https://facebook.github.io/react/docs/pure-render-mixin.html
我正在使用 Reflux.connectFilter mixin 让一堆 Graph 组件监听我的 GraphStore 中的变化。使用过滤器,它们应该仅在 GraphStore 的图形数组中与其 ID 匹配的元素发生更改(或 added/removed)时才重新呈现。但是,当我更新数组的单个元素时,比如通过设置名称变量,我仍然看到所有正在侦听的图形都重新呈现。我做错了什么吗?
GraphStore
var Reflux = require('reflux');
var GraphActions = require('./graphActions').GraphActions;
var GraphStore = Reflux.createStore({
listenables: [GraphActions],
init: function() {
this.graphs = [];
this.metricMetaData = {};
},
onAddGraph: function(graphId, name) { // Called only by the Dashboard component that is a parent to all Graphs
this.graphs.push(
{
id: graphId,
name: ""
}
);
this.updateGraphs();
},
onSetName: function(graphId, name) { // Called only by the Dashboard component that is a parent to all Graphs
for(var i = 0, gl = this.graphs.length; i < gl; ++i) {
if(this.graphs[i].id === graphId) {
this.graphs[i].name = name;
this.updateGraphs();
return;
}
}
},
...
updateGraphs: function() {
this.trigger(this.graphs); // This is the only place in the store where trigger is called
},
getInitialState: function() {
return this.graphs;
}
});
module.exports = {GraphStore: GraphStore};
图表
/** @jsx React.DOM */
var React = require('react');
var Reflux = require('reflux');
var GraphActions = require('./graphActions').GraphActions;
var GraphStore = require('./graphStore').GraphStore;
var Graph = React.createClass({
mixins: [Reflux.connectFilter(GraphStore, "graph", function(graphs) {
return graphs.filter(function(graph) {
return graph.id === this.props.id;
}.bind(this))[0];
})],
propTypes: {
id: React.PropTypes.string.isRequired
},
...
render: function() {
if(typeof this.state.graph === "undefined") {
return (<div>The graph has not been created in the store yet</div>);
} else {
return (<div>Graph name: {this.state.graph.name}</div>);
}
}
};
module.exports = {Graph: Graph};
仪表板
/** @jsx React.DOM */
var React = require('react');
var Graph = require('./graph').graph;
var GraphActions = require('./graphActions').GraphActions;
var UUID = require('uuid');
var Dashboard = React.createClass({
propTypes: {
numGraphs: React.PropTypes.int.isRequired
},
...
render: function() {
var graphs = [];
for(var i = 0; i < this.props.numGraphs; ++i) {
var currId = UUID.v4();
GraphActions.addGraph(currId, "");
graphs.push(<Graph id={currId} />);
}
return (<div>{graphs}</div>);
}
};
module.exports = {Dashboard: Dashboard};
我没用过 Reflux,但我认为这里的问题是你所有的 Graph
实例都在监听 GraphStore
,一旦那个商店发送一个事件,所有组件实例将收到该事件。他们会过滤掉他们不感兴趣的数据,但 Reflux 仍然会在所有实例上调用 setState
,触发它们重新渲染。如果过滤函数的结果与之前相同,Reflux 不会(据我所知)短路重新渲染。
要将它短路并避免在取回相同数据时重新渲染,您需要在组件上实现 shouldComponentUpdate
方法并将新状态与旧状态进行比较,并且 return 如果相同则为假。
一种流行的方法是将 [1] Immutable.js 与 [2] PureRenderMixin 一起使用,后者会为您短路。
[1] https://github.com/facebook/immutable-js
[2]https://facebook.github.io/react/docs/pure-render-mixin.html