Coveralls logob
Coveralls logo
  • Home
  • Features
  • Pricing
  • Docs
  • Sign In

uber / deck.gl / 13779

18 Sep 2019 - 0:00 coverage decreased (-2.9%) to 79.902%
13779

Pull #3623

travis-ci-com

9181eb84f9c35729a3bad740fb7f9d93?size=18&default=identiconweb-flow
beta.2
Pull Request #3623: Bump dependency versions

3405 of 4619 branches covered (73.72%)

Branch coverage included in aggregate %.

7031 of 8442 relevant lines covered (83.29%)

5687.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.78
/modules/react/src/deckgl.js
1
// Copyright (c) 2015 - 2017 Uber Technologies, Inc.
13×
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a copy
4
// of this software and associated documentation files (the "Software"), to deal
5
// in the Software without restriction, including without limitation the rights
6
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
// copies of the Software, and to permit persons to whom the Software is
8
// furnished to do so, subject to the following conditions:
9
//
10
// The above copyright notice and this permission notice shall be included in
11
// all copies or substantial portions of the Software.
12
//
13
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
// THE SOFTWARE.
20

21
import React, {createElement} from 'react';
22
import PropTypes from 'prop-types';
23
import {Deck, experimental} from '@deck.gl/core';
24
const {memoize} = experimental;
1×
25

26
import extractJSXLayers from './utils/extract-jsx-layers';
27
import positionChildrenUnderViews from './utils/position-children-under-views';
28

29
const propTypes = Deck.getPropTypes(PropTypes);
1×
30

31
const defaultProps = Deck.defaultProps;
1×
32

33
export default class DeckGL extends React.Component {
34
  constructor(props) {
35
    super(props);
2×
36

37
    this.viewports = null;
2×
38
    this.children = null;
2×
39

40
    // The redraw flag of deck
41
    this._needsRedraw = null;
2×
42

43
    // Bind public methods
44
    this.pickObject = this.pickObject.bind(this);
2×
45
    this.pickMultipleObjects = this.pickMultipleObjects.bind(this);
2×
46
    this.pickObjects = this.pickObjects.bind(this);
2×
47

48
    // Memoized functions
49
    this._extractJSXLayers = memoize(extractJSXLayers);
2×
50
    this._positionChildrenUnderViews = memoize(positionChildrenUnderViews);
2×
51
  }
52

53
  componentDidMount() {
54
    // Allows a subclass of Deck to be used
55
    // TODO - update propTypes / defaultProps?
56
    const DeckClass = this.props.Deck || Deck;
2×
57

58
    // DEVTOOLS can cause this to be called twice
59
    this.deck =
2×
60
      this.deck ||
61
      new DeckClass(
62
        Object.assign({}, this.props, {
63
          canvas: this.deckCanvas,
64
          // The Deck's animation loop is independent from React's render cycle, causing potential
65
          // synchronization issues. We provide this custom render function to make sure that React
66
          // and Deck update on the same schedule.
67
          _customRender: this._customRender.bind(this)
68
        })
69
      );
70
    this._updateFromProps(this.props);
2×
71
  }
72

73
  // This method checks if React needs to call `render`.
74
  // Props changes may lead to 3 types of updates:
75
  // 1. Only the WebGL context - updated in Deck's render cycle (next animation frame)
76
  // 2. Only the DOM - updated in React's lifecycle (now)
77
  // 3. Both the WebGL context and the DOM - defer React rerender to next animation frame just
78
  //    before Deck redraw to ensure perfect synchronization & avoid excessive redraw
79
  //    This is because multiple changes may happen to Deck between two frames e.g. transition
80
  shouldComponentUpdate(nextProps) {
81
    // Update Deck's props. If Deck needs redraw, this will trigger a call to `_customRender` in
82
    // the next animation frame.
UNCOV
83
    this._updateFromProps(nextProps);
!
84

85
    // If the child components have changed, React needs to rerender (case 2 or 3)
UNCOV
86
    const childrenChanged = this.children !== this._parseJSX(nextProps).children;
!
87
    // If the views have changed, both React and WebGL context need update (case 3)
UNCOV
88
    const viewsChanged = this.deck.viewManager && this.deck.viewManager.needsRedraw();
Branches [[2, 0], [2, 1]] missed. !
89

90
    // Only call `render` right away in case 2
UNCOV
91
    return childrenChanged && !viewsChanged;
Branches [[3, 0], [3, 1]] missed. !
92
  }
93

94
  componentDidUpdate() {
95
    // render has just been called. The children are positioned based on the current view state.
96
    // Redraw Deck canvas immediately, if necessary, using the current view state, so that it
97
    // matches the child components.
98
    this._redrawDeck();
1×
99
  }
100

101
  componentWillUnmount() {
102
    this.deck.finalize();
2×
103
  }
104

105
  // Public API
106

107
  pickObject(opts) {
UNCOV
108
    return this.deck.pickObject(opts);
!
109
  }
110

111
  pickMultipleObjects(opts) {
UNCOV
112
    return this.deck.pickMultipleObjects(opts);
!
113
  }
114

115
  pickObjects(opts) {
UNCOV
116
    return this.deck.pickObjects(opts);
!
117
  }
118

119
  // Callbacks
120
  _redrawDeck() {
121
    if (this._needsRedraw) {
Branches [[4, 1]] missed. 1×
122
      // Only redraw it we have received a dirty flag
123
      this.deck._drawLayers(this._needsRedraw);
1×
124
      this._needsRedraw = null;
1×
125
    }
126
  }
127

128
  _customRender(redrawReason) {
129
    // Save the dirty flag for later
130
    this._needsRedraw = redrawReason;
1×
131

132
    // Viewport/view state is passed to child components as props.
133
    // If they have changed, we need to trigger a React rerender to update children props.
134
    const viewports = this.deck.viewManager.getViewports();
1×
135
    if (viewports !== this.viewports) {
Branches [[5, 1]] missed. 1×
136
      // Viewports have changed, update children props first.
137
      // This will delay the Deck canvas redraw till after React update (in componentDidUpdate)
138
      // so that the canvas does not get rendered before the child components update.
139
      this.forceUpdate();
1×
140
    } else {
141
      this._redrawDeck();
!
142
    }
143
  }
144

145
  // Private Helpers
146

147
  _parseJSX(props) {
148
    return this._extractJSXLayers({
5×
149
      layers: props.layers,
150
      views: props.views,
151
      children: props.children
152
    });
153
  }
154

155
  // 1. Extract any JSX layers from the react children
156
  // 2. Handle any backwards compatiblity props for React layer
157
  // Needs to be called both from initial mount, and when new props are received
158
  _updateFromProps(props) {
159
    // extract any deck.gl layers masquerading as react elements from props.children
160
    const {layers, views} = this._parseJSX(props);
2×
161
    const deckProps = Object.assign({}, props, {
2×
162
      layers,
163
      views
164
    });
165

166
    this.deck.setProps(deckProps);
2×
167
  }
168

169
  render() {
170
    // Save the viewports and children used for this render
171
    const {viewManager} = this.deck || {};
3×
172
    this.viewports = viewManager && viewManager.getViewports();
3×
173
    this.children = this._parseJSX(this.props).children;
3×
174

175
    // Render the background elements (typically react-map-gl instances)
176
    // using the view descriptors
177
    const children = this._positionChildrenUnderViews({
3×
178
      children: this.children,
179
      viewports: this.viewports,
180
      deck: this.deck,
181
      ContextProvider: this.props.ContextProvider
182
    });
183

184
    // TODO - this styling is enforced for correct positioning with children
185
    // It can override the styling set by `Deck`, this should be consolidated.
186
    // Note that width and height are handled by deck.gl
187
    const style = Object.assign({}, {position: 'absolute', left: 0, top: 0}, this.props.style);
3×
188

189
    const canvas = createElement('canvas', {
3×
190
      ref: c => (this.deckCanvas = c),
6×
191
      key: 'deck-canvas',
192
      id: this.props.id,
193
      style
194
    });
195

196
    // Render deck.gl as the last child
197
    return createElement('div', {id: 'deckgl-wrapper'}, [children, canvas]);
3×
198
  }
199
}
200

201
DeckGL.propTypes = propTypes;
1×
202
DeckGL.defaultProps = defaultProps;
1×
Troubleshooting · Open an Issue · Sales · Support · ENTERPRISE · CAREERS · STATUS
BLOG · TWITTER · Legal & Privacy · Supported CI Services · What's a CI service? · Automated Testing

© 2019 Coveralls, LLC