Using deck.gl with React
While not directly based on React, deck.gl is designed from ground up to work with React based applications. deck.gl layers fit naturally into React's component render flow and flux/redux based applications. deck.gl layers will be performantly rerendered whenever you rerender your normal JSX or React components.
The DeckGL React Component
To use deck.gl with React, simply import the DeckGL
React component and render it as a child of another component, passing in your list of deck.gl layers as a property.
/// app.js
import React from 'react';
import DeckGL from '@deck.gl/react';
import {LineLayer} from '@deck.gl/layers';
// Viewport settings
const INITIAL_VIEW_STATE = {
longitude: -122.41669,
latitude: 37.7853,
zoom: 13,
pitch: 0,
bearing: 0
};
// Data to be used by the LineLayer
const data = [
{sourcePosition: [-122.41669, 37.7853], targetPosition: [-122.41669, 37.781]}
];
// DeckGL react component
function App() {
const layers = [
new LineLayer({id: 'line-layer', data})
];
return <DeckGL
initialViewState={INITIAL_VIEW_STATE}
controller={true}
layers={layers} />;
}
Adding a Base Map
An important companion to deck.gl is react-map-gl
. It is a React wrapper for Mapbox that can share the same web mercator viewport settings.
/// app.js
import React from 'react';
import DeckGL from '@deck.gl/react';
import {LineLayer} from '@deck.gl/layers';
import {Map} from 'react-map-gl';
// Set your mapbox access token here
const MAPBOX_ACCESS_TOKEN = 'your_mapbox_token';
// Viewport settings
const INITIAL_VIEW_STATE = {
longitude: -122.41669,
latitude: 37.7853,
zoom: 13,
pitch: 0,
bearing: 0
};
// Data to be used by the LineLayer
const data = [
{sourcePosition: [-122.41669, 37.7853], targetPosition: [-122.41669, 37.781]}
];
function App({data}) {
const layers = [
new LineLayer({id: 'line-layer', data})
];
return (
<DeckGL
initialViewState={INITIAL_VIEW_STATE}
controller={true}
layers={layers}
>
<Map mapboxAccessToken={MAPBOX_ACCESS_TOKEN} />
</DeckGL>
);
}
For more detailed examples and options, see using with Mapbox.
Using JSX with deck.gl Layers
It is possible to use JSX syntax to create deck.gl layers as React children of the DeckGL
React components, instead of providing them as ES6 class instances to the layers
prop. There are no performance advantages to this syntax but it can allow for a more consistent, React-like coding style.
function App() {
return (
<DeckGL
initialViewState={INITIAL_VIEW_STATE}
controller={true} >
<LineLayer id="line-layer" data={data} />
</DeckGL>
);
}
For more information on this syntax and its limitations, see DeckGL API.
Using JSX with deck.gl views
It is possible to use JSX syntax to create deck.gl views as React children of the DeckGL
React components, instead of providing them as ES6 class instances to the views
prop.
The following code renders the same set of layers in two viewports, splitting the canvas into two columns:
import {MapView, FirstPersonView} from '@deck.gl/core';
function App() {
const layers = [
new LineLayer({id: 'line-layer', data})
];
return (
<DeckGL
initialViewState={INITIAL_VIEW_STATE}
controller={true}
layers={layers} >
<MapView id="map" width="50%" controller={true}>
<Map mapboxAccessToken={MAPBOX_ACCESS_TOKEN} />
</MapView>
<FirstPersonView width="50%" x="50%" fovy={50} />
</DeckGL>
);
}
For more information on this syntax, see DeckGL API.
Using deck.gl with SSR
Frameworks such as Next.js
and Gatsby
leverage Server Side Rendering to improve page loading performance. Some of deck.gl's upstream dependencies, such as d3
, have opted to become ES modules and no longer support require()
from the default Node entry point. This will cause SSR to fail. Possible mitigations are:
- If the framework provides such a config, you may be able to replace the offending commonjs entry point (e.g.
@deck.gl/layers
) with the corresponding ESM entry point (@deck.gl/layers/dist/esm
). - Otherwise, isolate the deck.gl imports and exclude them from SSR. Since deck.gl renders into a WebGL2/WebGPU context, it wouldn't benefit from SSR to begin with. Below is a minimal sample for
Next.js
:
import DeckGL, {TextLayer} from 'deck.gl';
export default function Map() {
return <DeckGL ... />
}
import dynamic from 'next/dynamic';
const Map = dynamic(() => import('../components/map'), {ssr: false});
export default function App() {
return <Map />;
}
More examples are discussed in this issue.
Remarks
The
DeckGL
component is typically rendered as a child of a map component like react-map-gl, but could be rendered as a child of any React component that you want to overlay your layers on top of.To achieve the overlay effect, the
DeckGL
component creates a transparentcanvas
DOM element, into which the deck.gl layers passed in thelayers
prop will render (using WebGL2/WebGPU). Since this canvas is transparent, any other component you have underneath (typically a map) will visible behind the layers.When the deck.gl layer list is drawn to screen, it matches the new Layer instances with the instances from the previous render call, intelligently compares the new properties and only updates GPU resources when needed (just like React does for DOM components).
Internally, the
DeckGL
component initializes a WebGL2/WebGPU context attached to a canvas element, sets up the animation loop and calls provided callbacks on initial load and for each rendered frame. TheDeckGL
component also handles events propagation across layers, and prevents unnecessary calculations using React and deck.gl lifecycle functions.
See full API doc for the DeckGL
component.