From a1b8e963dc08ef5e1f98d3c2df6c92c776950bd6 Mon Sep 17 00:00:00 2001 From: Simon Howe Date: Tue, 6 Sep 2016 16:06:19 +0200 Subject: [PATCH] nodes-chart only re-rendered on prop updates!!! --- client/app/scripts/charts/node-container.js | 2 ++ client/app/scripts/charts/nodes-chart.js | 29 ++++++++++++++-- client/app/scripts/charts/nodes-grid.js | 2 ++ client/app/scripts/components/app.js | 2 ++ client/app/scripts/components/nodes.js | 26 +------------- .../app/scripts/selectors/chartSelectors.js | 34 +++++++++++++++++-- client/app/scripts/utils/topology-utils.js | 1 + 7 files changed, 65 insertions(+), 31 deletions(-) diff --git a/client/app/scripts/charts/node-container.js b/client/app/scripts/charts/node-container.js index 74820303d..9e6b5fb66 100644 --- a/client/app/scripts/charts/node-container.js +++ b/client/app/scripts/charts/node-container.js @@ -13,6 +13,8 @@ class NodeContainer extends React.Component { const scaleFactor = focused ? (1 / zoomScale) : 1; const other = _.omit(this.props, 'dx', 'dy'); + console.log('nodecontainer.render'); + return ( = 50) { + precision = 0; + } else if (nodesCount > 20) { + precision = 1; + } else if (nodesCount > 10) { + precision = 2; + } else { + precision = 3; + } + + return precision; +} + function identityPresevingMerge(a, b) { // @@ -152,6 +172,7 @@ class NodesChart extends React.Component { } componentWillReceiveProps(nextProps) { + console.log('componentWillReceiveProps', diff(nextProps, this.props), nextProps); // gather state, setState should be called only once here const state = _.assign({}, this.state); @@ -224,6 +245,7 @@ class NodesChart extends React.Component { const svgClassNames = this.props.isEmpty ? 'hide' : ''; console.log('nodes-chart.render'); + const layoutPrecision = getLayoutPrecision(nodes.size); return (
+ layoutPrecision={layoutPrecision} />
); @@ -411,7 +433,8 @@ class NodesChart extends React.Component { function mapStateToProps(state) { return { - adjacentNodes: getAdjacentNodes(state), + nodes: nodeAdjacenciesSelector(state), + adjacentNodes: adjacentNodesSelector(state), forceRelayout: state.get('forceRelayout'), selectedNodeId: state.get('selectedNodeId'), topologyId: state.get('currentTopologyId'), diff --git a/client/app/scripts/charts/nodes-grid.js b/client/app/scripts/charts/nodes-grid.js index e05172f7d..6456c0224 100644 --- a/client/app/scripts/charts/nodes-grid.js +++ b/client/app/scripts/charts/nodes-grid.js @@ -5,6 +5,7 @@ import { connect } from 'react-redux'; import { List as makeList, Map as makeMap } from 'immutable'; import NodeDetailsTable from '../components/node-details/node-details-table'; import { clickNode, sortOrderChanged } from '../actions/app-actions'; +import { nodesSelector } from '../selectors/chartSelectors'; import { getNodeColor } from '../utils/color-utils'; @@ -142,6 +143,7 @@ class NodesGrid extends React.Component { function mapStateToProps(state) { return { + nodes: nodesSelector(state), gridSortBy: state.get('gridSortBy'), gridSortedDesc: state.get('gridSortedDesc'), currentTopology: state.get('currentTopology'), diff --git a/client/app/scripts/components/app.js b/client/app/scripts/components/app.js index b324ce059..3621f64e9 100644 --- a/client/app/scripts/components/app.js +++ b/client/app/scripts/components/app.js @@ -142,6 +142,7 @@ class App extends React.Component { } } + function mapStateToProps(state) { return { activeTopologyOptions: getActiveTopologyOptions(state), @@ -158,6 +159,7 @@ function mapStateToProps(state) { }; } + export default connect( mapStateToProps )(App); diff --git a/client/app/scripts/components/nodes.js b/client/app/scripts/components/nodes.js index c96a9f22e..385d64910 100644 --- a/client/app/scripts/components/nodes.js +++ b/client/app/scripts/components/nodes.js @@ -8,30 +8,11 @@ import { DelayedShow } from '../utils/delayed-show'; import { Loading, getNodeType } from './loading'; import { isTopologyEmpty } from '../utils/topology-utils'; import { CANVAS_MARGINS } from '../constants/styles'; -import { nodesSelector } from '../selectors/chartSelectors'; const navbarHeight = 194; const marginTop = 0; -/** - * dynamic coords precision based on topology size - */ -function getLayoutPrecision(nodesCount) { - let precision; - if (nodesCount >= 50) { - precision = 0; - } else if (nodesCount > 20) { - precision = 1; - } else if (nodesCount > 10) { - precision = 2; - } else { - precision = 3; - } - - return precision; -} - class Nodes extends React.Component { constructor(props, context) { super(props, context); @@ -68,9 +49,8 @@ class Nodes extends React.Component { } render() { - const { nodes, topologyEmpty, gridMode, topologiesLoaded, nodesLoaded, topologies, + const { topologyEmpty, gridMode, topologiesLoaded, nodesLoaded, topologies, currentTopology } = this.props; - const layoutPrecision = getLayoutPrecision(nodes.size); console.log('nodes.render'); @@ -87,13 +67,10 @@ class Nodes extends React.Component { {gridMode ? : } ); @@ -116,7 +93,6 @@ function mapStateToProps(state) { return { currentTopology: state.get('currentTopology'), gridMode: state.get('gridMode'), - nodes: nodesSelector(state), nodesLoaded: state.get('nodesLoaded'), topologies: state.get('topologies'), topologiesLoaded: state.get('topologiesLoaded'), diff --git a/client/app/scripts/selectors/chartSelectors.js b/client/app/scripts/selectors/chartSelectors.js index 9ca929b53..9d730c96a 100644 --- a/client/app/scripts/selectors/chartSelectors.js +++ b/client/app/scripts/selectors/chartSelectors.js @@ -1,5 +1,15 @@ -import { createSelector } from 'reselect'; -import { Map as makeMap } from 'immutable'; +import { createSelector, createSelectorCreator, defaultMemoize } from 'reselect'; +import { Map as makeMap, is } from 'immutable'; + +import { getAdjacentNodes } from '../utils/topology-utils'; + + +// imm createSelector +// +const imCreateSelector = createSelectorCreator( + defaultMemoize, + is +); const allNodesSelector = state => state.get('nodes'); @@ -11,7 +21,7 @@ export const nodesSelector = createSelector( ); -export const nodeAdjacenciesSelector = createSelector( +export const _nodeAdjacenciesSelector = createSelector( nodesSelector, (nodes) => nodes.map(n => makeMap({ id: n.get('id'), @@ -20,6 +30,24 @@ export const nodeAdjacenciesSelector = createSelector( ); +export const nodeAdjacenciesSelector = imCreateSelector( + _nodeAdjacenciesSelector, + (nodes) => nodes +); + + +const _adjacentNodesSelector = createSelector( + getAdjacentNodes, + (ns) => ns +); + + +export const adjacentNodesSelector = imCreateSelector( + _adjacentNodesSelector, + (adjacentNodes) => adjacentNodes +); + + export const layoutNodesSelector = (_, props) => props.layoutNodes; diff --git a/client/app/scripts/utils/topology-utils.js b/client/app/scripts/utils/topology-utils.js index f58b1e8c1..975943598 100644 --- a/client/app/scripts/utils/topology-utils.js +++ b/client/app/scripts/utils/topology-utils.js @@ -143,6 +143,7 @@ export function isTopologyEmpty(state) { && state.get('nodes').size === 0; } + export function getAdjacentNodes(state, originNodeId) { let adjacentNodes = makeSet(); const nodeId = originNodeId || state.get('selectedNodeId');