Skip to content

Commit

Permalink
improve react perf (#2949)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pessimistress committed Apr 11, 2019
1 parent bd12236 commit 3f47a95
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 73 deletions.
6 changes: 4 additions & 2 deletions modules/core/src/index.js
Expand Up @@ -79,8 +79,9 @@ export {default as log} from './utils/log';
import {flattenVertices, fillArray} from './utils/flatten'; // Export? move to luma.gl or math.gl?

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

// lighting
export {AmbientLight, PointLight, DirectionalLight} from '@luma.gl/core';
Expand All @@ -91,5 +92,6 @@ export const experimental = {
Tesselator,
flattenVertices,
fillArray,
count
count,
memoize
};
96 changes: 25 additions & 71 deletions modules/react/src/deckgl.js
Expand Up @@ -20,10 +20,11 @@

import React, {createElement} from 'react';
import PropTypes from 'prop-types';
import {Deck, View, log} from '@deck.gl/core';
import {Deck, experimental} from '@deck.gl/core';
const {memoize} = experimental;

import extractJSXLayers from './utils/extract-jsx-layers';
import {inheritsFrom} from './utils/inherits-from';
import evaluateChildren from './utils/evaluate-children';
import positionChildrenUnderViews from './utils/position-children-under-views';
import autobind from './utils/autobind';

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

this.viewports = null;
this.children = [];

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

autobind(this);

// Memoized functions
this._extractJSXLayers = memoize(extractJSXLayers);
this._positionChildrenUnderViews = memoize(positionChildrenUnderViews);
}

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

queryObject(opts) {
log.removed('queryObject', 'pickObject')();
}

queryVisibleObjects(opts) {
log.removed('queryVisibleObjects', 'pickObjects')();
}

// Callbacks
_redrawDeck() {
if (this._needsRedraw) {
Expand Down Expand Up @@ -137,6 +133,14 @@ export default class DeckGL extends React.PureComponent {

// Private Helpers

_parseJSX() {
return this._extractJSXLayers({
layers: this.props.layers,
views: this.props.views,
children: this.props.children
});
}

// 1. Extract any JSX layers from the react children
// 2. Handle any backwards compatiblity props for React layer
// Needs to be called both from initial mount, and when props have changed
Expand All @@ -146,77 +150,27 @@ export default class DeckGL extends React.PureComponent {
}

// extract any deck.gl layers masquerading as react elements from props.children
const {layers, views, children} = extractJSXLayers(this.props);

const {layers, views} = this._parseJSX();
const deckProps = Object.assign({}, this.props, {
layers,
views
});

this.deck.setProps(deckProps);

this.children = children;
}

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

if (!viewManager || !viewManager.views.length) {
return [];
}

const defaultViewId = viewManager.views[0].id;
// Save the viewports used for the last render
this.viewports = viewManager.getViewports();

return children.map((child, i) => {
if (child.props.viewportId) {
log.removed('viewportId', '<View>')();
}
if (child.props.viewId) {
log.removed('viewId', '<View>')();
}

// Unless child is a View, position / render as part of the default view
let viewId = defaultViewId;
let viewChildren = child;
if (inheritsFrom(child.type, View)) {
viewId = child.props.id || defaultViewId;
viewChildren = child.props.children;
}

const viewport = viewManager.getViewport(viewId);
const viewState = viewManager.getViewState(viewId);

// Drop (auto-hide) elements with viewId that are not matched by any current view
if (!viewport) {
return null;
}

// Resolve potentially relative dimensions using the deck.gl container size
const {x, y, width, height} = viewport;

viewChildren = evaluateChildren(viewChildren, {
x,
y,
width,
height,
viewport,
viewState
});

const style = {position: 'absolute', left: x, top: y, width, height};
const key = `view-child-${viewId}-${i}`;
return createElement('div', {key, id: key, style}, viewChildren);
});
}

render() {
// Render the background elements (typically react-map-gl instances)
// using the view descriptors
const children = this._positionChildrenUnderViews(this.children);
const children = this._positionChildrenUnderViews({
children: this._parseJSX().children,
viewports: this.viewports,
deck: this.deck
});

// TODO - this styling is enforced for correct positioning with children
// It can override the styling set by `Deck`, this should be consolidated.
Expand Down
57 changes: 57 additions & 0 deletions modules/react/src/utils/position-children-under-views.js
@@ -0,0 +1,57 @@
import {createElement} from 'react';
import {View, log} from '@deck.gl/core';
import {inheritsFrom} from './inherits-from';
import evaluateChildren from './evaluate-children';

// Iterate over views and reposition children associated with views
// TODO - Can we supply a similar function for the non-React case?
export default function positionChildrenUnderViews({children, viewports, deck}) {
const {viewManager} = deck || {};

if (!viewManager || !viewManager.views.length) {
return [];
}

const defaultViewId = viewManager.views[0].id;

return children.map((child, i) => {
if (child.props.viewportId) {
log.removed('viewportId', '<View>')();
}
if (child.props.viewId) {
log.removed('viewId', '<View>')();
}

// Unless child is a View, position / render as part of the default view
let viewId = defaultViewId;
let viewChildren = child;
if (inheritsFrom(child.type, View)) {
viewId = child.props.id || defaultViewId;
viewChildren = child.props.children;
}

const viewport = viewManager.getViewport(viewId);
const viewState = viewManager.getViewState(viewId);

// Drop (auto-hide) elements with viewId that are not matched by any current view
if (!viewport) {
return null;
}

// Resolve potentially relative dimensions using the deck.gl container size
const {x, y, width, height} = viewport;

viewChildren = evaluateChildren(viewChildren, {
x,
y,
width,
height,
viewport,
viewState
});

const style = {position: 'absolute', left: x, top: y, width, height};
const key = `view-child-${viewId}-${i}`;
return createElement('div', {key, id: key, style}, viewChildren);
});
}

0 comments on commit 3f47a95

Please sign in to comment.