Skip to content

Commit 3f47a95

Browse files
improve react perf (visgl#2949)
1 parent bd12236 commit 3f47a95

File tree

3 files changed

+86
-73
lines changed

3 files changed

+86
-73
lines changed

modules/core/src/index.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,9 @@ export {default as log} from './utils/log';
7979
import {flattenVertices, fillArray} from './utils/flatten'; // Export? move to luma.gl or math.gl?
8080

8181
export {createIterable} from './utils/iterable-utils';
82-
import {default as Tesselator} from './utils/tesselator'; // Export? move to luma.gl or math.gl?
82+
import Tesselator from './utils/tesselator'; // Export? move to luma.gl or math.gl?
8383
import {count} from './utils/count';
84+
import memoize from './utils/memoize';
8485

8586
// lighting
8687
export {AmbientLight, PointLight, DirectionalLight} from '@luma.gl/core';
@@ -91,5 +92,6 @@ export const experimental = {
9192
Tesselator,
9293
flattenVertices,
9394
fillArray,
94-
count
95+
count,
96+
memoize
9597
};

modules/react/src/deckgl.js

+25-71
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@
2020

2121
import React, {createElement} from 'react';
2222
import PropTypes from 'prop-types';
23-
import {Deck, View, log} from '@deck.gl/core';
23+
import {Deck, experimental} from '@deck.gl/core';
24+
const {memoize} = experimental;
25+
2426
import extractJSXLayers from './utils/extract-jsx-layers';
25-
import {inheritsFrom} from './utils/inherits-from';
26-
import evaluateChildren from './utils/evaluate-children';
27+
import positionChildrenUnderViews from './utils/position-children-under-views';
2728
import autobind from './utils/autobind';
2829

2930
const propTypes = Deck.getPropTypes(PropTypes);
@@ -35,12 +36,15 @@ export default class DeckGL extends React.PureComponent {
3536
super(props);
3637

3738
this.viewports = null;
38-
this.children = [];
3939

4040
// The redraw flag of deck
4141
this._needsRedraw = null;
4242

4343
autobind(this);
44+
45+
// Memoized functions
46+
this._extractJSXLayers = memoize(extractJSXLayers);
47+
this._positionChildrenUnderViews = memoize(positionChildrenUnderViews);
4448
}
4549

4650
componentDidMount() {
@@ -101,14 +105,6 @@ export default class DeckGL extends React.PureComponent {
101105
return this.deck.pickObjects({x, y, width, height, layerIds});
102106
}
103107

104-
queryObject(opts) {
105-
log.removed('queryObject', 'pickObject')();
106-
}
107-
108-
queryVisibleObjects(opts) {
109-
log.removed('queryVisibleObjects', 'pickObjects')();
110-
}
111-
112108
// Callbacks
113109
_redrawDeck() {
114110
if (this._needsRedraw) {
@@ -137,6 +133,14 @@ export default class DeckGL extends React.PureComponent {
137133

138134
// Private Helpers
139135

136+
_parseJSX() {
137+
return this._extractJSXLayers({
138+
layers: this.props.layers,
139+
views: this.props.views,
140+
children: this.props.children
141+
});
142+
}
143+
140144
// 1. Extract any JSX layers from the react children
141145
// 2. Handle any backwards compatiblity props for React layer
142146
// Needs to be called both from initial mount, and when props have changed
@@ -146,77 +150,27 @@ export default class DeckGL extends React.PureComponent {
146150
}
147151

148152
// extract any deck.gl layers masquerading as react elements from props.children
149-
const {layers, views, children} = extractJSXLayers(this.props);
150-
153+
const {layers, views} = this._parseJSX();
151154
const deckProps = Object.assign({}, this.props, {
152155
layers,
153156
views
154157
});
155158

156159
this.deck.setProps(deckProps);
157-
158-
this.children = children;
159160
}
160161

161-
// Iterate over views and reposition children associated with views
162-
// TODO - Can we supply a similar function for the non-React case?
163-
_positionChildrenUnderViews(children) {
162+
render() {
163+
// Save the viewports used for this render
164164
const {viewManager} = this.deck || {};
165+
this.viewports = viewManager && viewManager.getViewports();
165166

166-
if (!viewManager || !viewManager.views.length) {
167-
return [];
168-
}
169-
170-
const defaultViewId = viewManager.views[0].id;
171-
// Save the viewports used for the last render
172-
this.viewports = viewManager.getViewports();
173-
174-
return children.map((child, i) => {
175-
if (child.props.viewportId) {
176-
log.removed('viewportId', '<View>')();
177-
}
178-
if (child.props.viewId) {
179-
log.removed('viewId', '<View>')();
180-
}
181-
182-
// Unless child is a View, position / render as part of the default view
183-
let viewId = defaultViewId;
184-
let viewChildren = child;
185-
if (inheritsFrom(child.type, View)) {
186-
viewId = child.props.id || defaultViewId;
187-
viewChildren = child.props.children;
188-
}
189-
190-
const viewport = viewManager.getViewport(viewId);
191-
const viewState = viewManager.getViewState(viewId);
192-
193-
// Drop (auto-hide) elements with viewId that are not matched by any current view
194-
if (!viewport) {
195-
return null;
196-
}
197-
198-
// Resolve potentially relative dimensions using the deck.gl container size
199-
const {x, y, width, height} = viewport;
200-
201-
viewChildren = evaluateChildren(viewChildren, {
202-
x,
203-
y,
204-
width,
205-
height,
206-
viewport,
207-
viewState
208-
});
209-
210-
const style = {position: 'absolute', left: x, top: y, width, height};
211-
const key = `view-child-${viewId}-${i}`;
212-
return createElement('div', {key, id: key, style}, viewChildren);
213-
});
214-
}
215-
216-
render() {
217167
// Render the background elements (typically react-map-gl instances)
218168
// using the view descriptors
219-
const children = this._positionChildrenUnderViews(this.children);
169+
const children = this._positionChildrenUnderViews({
170+
children: this._parseJSX().children,
171+
viewports: this.viewports,
172+
deck: this.deck
173+
});
220174

221175
// TODO - this styling is enforced for correct positioning with children
222176
// It can override the styling set by `Deck`, this should be consolidated.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {createElement} from 'react';
2+
import {View, log} from '@deck.gl/core';
3+
import {inheritsFrom} from './inherits-from';
4+
import evaluateChildren from './evaluate-children';
5+
6+
// Iterate over views and reposition children associated with views
7+
// TODO - Can we supply a similar function for the non-React case?
8+
export default function positionChildrenUnderViews({children, viewports, deck}) {
9+
const {viewManager} = deck || {};
10+
11+
if (!viewManager || !viewManager.views.length) {
12+
return [];
13+
}
14+
15+
const defaultViewId = viewManager.views[0].id;
16+
17+
return children.map((child, i) => {
18+
if (child.props.viewportId) {
19+
log.removed('viewportId', '<View>')();
20+
}
21+
if (child.props.viewId) {
22+
log.removed('viewId', '<View>')();
23+
}
24+
25+
// Unless child is a View, position / render as part of the default view
26+
let viewId = defaultViewId;
27+
let viewChildren = child;
28+
if (inheritsFrom(child.type, View)) {
29+
viewId = child.props.id || defaultViewId;
30+
viewChildren = child.props.children;
31+
}
32+
33+
const viewport = viewManager.getViewport(viewId);
34+
const viewState = viewManager.getViewState(viewId);
35+
36+
// Drop (auto-hide) elements with viewId that are not matched by any current view
37+
if (!viewport) {
38+
return null;
39+
}
40+
41+
// Resolve potentially relative dimensions using the deck.gl container size
42+
const {x, y, width, height} = viewport;
43+
44+
viewChildren = evaluateChildren(viewChildren, {
45+
x,
46+
y,
47+
width,
48+
height,
49+
viewport,
50+
viewState
51+
});
52+
53+
const style = {position: 'absolute', left: x, top: y, width, height};
54+
const key = `view-child-${viewId}-${i}`;
55+
return createElement('div', {key, id: key, style}, viewChildren);
56+
});
57+
}

0 commit comments

Comments
 (0)