Skip to content

Commit aba1109

Browse files
Ihor DykhtaIhor Dykhta
authored andcommitted
update custom reducer example
Signed-off-by: Ihor Dykhta <ihordykhta@Ihors-MacBook-Pro.local>
1 parent 9d05b34 commit aba1109

11 files changed

Lines changed: 139 additions & 153 deletions

File tree

examples/custom-reducer/.babelrc

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# https://yarnpkg.com/configuration/yarnrc
2+
nodeLinker: node-modules
3+
# Define the registry to use when fetching packages.
4+
npmRegistryServer: 'https://registry.yarnpkg.com'

examples/custom-reducer/README.md

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
11
# Customize kepler.gl Reducer
22

3-
This example demos how to customize kepler.gl reducer
3+
Demo showing how to customize the kepler.gl reducer:
44

5-
1. Customize reducer initialState by `keplerGlReducer.initialState`
6-
2. Adding custom actions by `keplerGlReducer.plugins`
5+
1. Customize reducer initial state via `keplerGlReducer.initialState`
6+
2. Add custom actions via `keplerGlReducer.plugin`
77

8-
### Local dev
8+
## Pre-requirements
99

10-
```
11-
yarn
12-
```
10+
- [Node.js ^20.x](http://nodejs.org)
11+
- [Yarn 4.4.0](https://yarnpkg.com): See the [installation instructions][yarn-install].
1312

14-
add mapbox access token to node env
13+
## 1. Install Dependencies
1514

16-
```
17-
export MapboxAccessToken=<your_mapbox_token>
15+
Go to the `examples/custom-reducer` directory and run:
16+
17+
```sh
18+
touch yarn.lock && yarn
1819
```
1920

20-
then
21+
> `touch yarn.lock` is required once to mark this directory as a standalone Yarn project,
22+
> independent of the monorepo root.
2123
22-
```
24+
## 2. Start the App
25+
26+
```sh
2327
yarn start
2428
```
29+
30+
The app will be available at [http://localhost:8080](http://localhost:8080).
31+
32+
## Production Build
33+
34+
```sh
35+
yarn build
36+
```
37+
38+
The output will be in the `dist/` directory.
39+
40+
[yarn-install]: https://yarnpkg.com/getting-started/install

examples/custom-reducer/esbuild.config.mjs

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,57 @@
22
// Copyright contributors to the kepler.gl project
33

44
import esbuild from 'esbuild';
5-
import {replace} from 'esbuild-plugin-replace';
65
import {dotenvRun} from '@dotenv-run/esbuild';
76
import copyPlugin from 'esbuild-plugin-copy';
87

98
import process from 'node:process';
109
import fs from 'node:fs';
10+
import path from 'node:path';
11+
import {fileURLToPath} from 'node:url';
1112
import {spawn} from 'node:child_process';
12-
import {join} from 'node:path';
1313

1414
const args = process.argv;
1515

16+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
17+
1618
const port = 8080;
1719

1820
const NODE_ENV = JSON.stringify(process.env.NODE_ENV || 'production');
1921

20-
// Ensure a single instance of React and friends to avoid invalid hook calls
21-
const ROOT_NODE_MODULES = join('..', '..', 'node_modules');
22-
const thirdPartyAliases = {
23-
react: join(ROOT_NODE_MODULES, 'react'),
24-
'react-dom': join(ROOT_NODE_MODULES, 'react-dom'),
25-
'react-redux': join(ROOT_NODE_MODULES, 'react-redux', 'lib'),
26-
'styled-components': join(ROOT_NODE_MODULES, 'styled-components'),
27-
'apache-arrow': join(ROOT_NODE_MODULES, 'apache-arrow')
28-
};
29-
3022
const config = {
3123
platform: 'browser',
3224
format: 'iife',
3325
logLevel: 'info',
34-
loader: {
35-
'.js': 'jsx',
36-
'.css': 'css',
37-
'.ttf': 'file',
38-
'.woff': 'file',
39-
'.woff2': 'file'
40-
},
26+
loader: {'.js': 'jsx', '.css': 'css'},
4127
entryPoints: ['src/main.js'],
4228
outfile: 'dist/bundle.js',
4329
bundle: true,
4430
define: {
45-
NODE_ENV,
46-
'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken || '')
31+
NODE_ENV
4732
},
4833
plugins: [
4934
dotenvRun({
5035
verbose: true,
5136
environment: NODE_ENV,
5237
root: '../../.env'
5338
}),
54-
replace({
55-
__PACKAGE_VERSION__: '3.1.10',
56-
include: /constants\/src\/default-settings\.ts/
57-
}),
39+
// styled-components: @hubble.gl/react nests its own copy.
40+
// react-palm: several @kepler.gl/* packages nest their own copy.
41+
// Both are singletons that break when loaded more than once.
42+
{
43+
name: 'dedupe-singletons',
44+
setup(build) {
45+
build.onResolve({filter: /^(styled-components|react-palm(\/|$)|react$|react-dom$)/}, async args => {
46+
if (args.pluginData?.deduped) return;
47+
const result = await build.resolve(args.path, {
48+
resolveDir: __dirname,
49+
kind: args.kind,
50+
pluginData: {deduped: true}
51+
});
52+
return result;
53+
});
54+
}
55+
},
5856
copyPlugin({
5957
resolveFrom: 'cwd',
6058
assets: {
@@ -82,16 +80,13 @@ function openURL(url) {
8280
const result = await esbuild
8381
.build({
8482
...config,
85-
alias: thirdPartyAliases,
8683
minify: true,
8784
sourcemap: false,
8885
metafile: true,
8986
define: {
9087
...config.define,
9188
'process.env.NODE_ENV': '"production"'
92-
},
93-
drop: ['console', 'debugger'],
94-
treeShaking: true
89+
}
9590
})
9691
.catch(e => {
9792
console.error(e);
@@ -104,7 +99,6 @@ function openURL(url) {
10499
await esbuild
105100
.context({
106101
...config,
107-
alias: thirdPartyAliases,
108102
minify: false,
109103
sourcemap: true,
110104
banner: {
@@ -121,7 +115,7 @@ function openURL(url) {
121115
console.info(remoteAddress, status, `"${method} ${path}" [${timeInMS}ms]`);
122116
}
123117
});
124-
console.info(`kepler.gl custom-reducer example running at ${`http://localhost:${port}`}`);
118+
console.info(`kepler.gl custom-reducer example running at http://localhost:${port}`);
125119
openURL(`http://localhost:${port}`);
126120
})
127121
.catch(e => {
Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
{
2+
"name": "kepler-custom-reducer",
3+
"version": "0.0.1",
4+
"license": "MIT",
25
"scripts": {
36
"start": "node esbuild.config.mjs --start",
47
"build": "node esbuild.config.mjs --build",
58
"start-local": "NODE_ENV=local node esbuild.config.mjs --start"
69
},
710
"dependencies": {
8-
"@kepler.gl/actions": "^3.1.10",
9-
"@kepler.gl/components": "^3.1.10",
10-
"@kepler.gl/reducers": "^3.1.10",
11-
"global": "^4.3.0",
12-
"react": "^18.2.0",
13-
"react-dom": "^18.2.0",
14-
"react-palm": "^3.3.6",
15-
"react-redux": "^8.0.5",
16-
"react-virtualized": "^9.21.0",
17-
"redux-actions": "^2.2.1",
18-
"styled-components": "6.4.3"
11+
"@kepler.gl/actions": "^3.3.0-alpha.6",
12+
"@kepler.gl/components": "^3.3.0-alpha.6",
13+
"@kepler.gl/reducers": "^3.3.0-alpha.6",
14+
"react": "^19.0.0",
15+
"react-dom": "^19.0.0",
16+
"react-redux": "^9.1.0",
17+
"redux": "^5.0.1"
1918
},
2019
"devDependencies": {
2120
"@dotenv-run/esbuild": "^1.5.0",
21+
"@types/node": "^20",
22+
"@types/react": "^19.0.0",
23+
"@types/react-dom": "^19.0.0",
2224
"esbuild": "^0.25.0",
2325
"esbuild-plugin-copy": "^2.1.1",
24-
"esbuild-plugin-replace": "^1.4.0"
26+
"typescript": "^5.5.0"
2527
}
2628
}
Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,23 @@
11
// SPDX-License-Identifier: MIT
22
// Copyright contributors to the kepler.gl project
33

4-
import {createAction, handleActions} from 'redux-actions';
5-
64
// CONSTANTS
75
export const INIT = 'INIT';
86

9-
// ACTIONS
10-
export const appInit = createAction(INIT);
11-
12-
// INITIAL_STATE
7+
// INITIAL STATE
138
const initialState = {
149
appName: 'example',
1510
loaded: false
1611
};
1712

1813
// REDUCER
19-
const appReducer = handleActions(
20-
{
21-
[INIT]: state => ({
22-
...state,
23-
loaded: true
24-
})
25-
},
26-
initialState
27-
);
14+
const appReducer = (state = initialState, action) => {
15+
switch (action.type) {
16+
case INIT:
17+
return {...state, loaded: true};
18+
default:
19+
return state;
20+
}
21+
};
2822

2923
export default appReducer;

examples/custom-reducer/src/app.js

Lines changed: 34 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,44 @@
11
// SPDX-License-Identifier: MIT
22
// Copyright contributors to the kepler.gl project
33

4-
import React, {Component} from 'react';
5-
import {connect} from 'react-redux';
6-
import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';
4+
import * as React from 'react';
5+
import {useState, useEffect} from 'react';
6+
import {useDispatch} from 'react-redux';
77
import KeplerGl from '@kepler.gl/components';
8-
import {createAction} from 'redux-actions';
9-
108
import {addDataToMap, wrapTo} from '@kepler.gl/actions';
9+
1110
import sampleData from './data/sample-data';
1211
import config from './configurations/config';
1312

14-
const MAPBOX_TOKEN = process.env.MapboxAccessToken; // eslint-disable-line
15-
16-
// extra actions plugged into kepler.gl reducer (store.js)
17-
const hideAndShowSidePanel = createAction('HIDE_AND_SHOW_SIDE_PANEL');
18-
19-
class App extends Component {
20-
componentDidMount() {
21-
this.props.dispatch(
22-
wrapTo(
23-
'map1',
24-
addDataToMap({
25-
datasets: sampleData,
26-
config
27-
})
28-
)
29-
);
30-
}
31-
32-
_toggleSidePanelVisibility = () => {
33-
this.props.dispatch(wrapTo('map1', hideAndShowSidePanel()));
34-
};
35-
36-
render() {
37-
return (
38-
<div style={{position: 'absolute', width: '100%', height: '100%'}}>
39-
<button onClick={this._toggleSidePanelVisibility}> Hide / Show Side Panel</button>
40-
<AutoSizer>
41-
{({height, width}) => (
42-
<KeplerGl mapboxApiAccessToken={MAPBOX_TOKEN} id="map1" width={width} height={height} />
43-
)}
44-
</AutoSizer>
45-
</div>
46-
);
47-
}
13+
// Extra action handled by the custom kepler.gl reducer plugin (see store.js)
14+
const hideAndShowSidePanel = () => ({type: 'HIDE_AND_SHOW_SIDE_PANEL'});
15+
16+
function useWindowSize() {
17+
const [size, setSize] = useState({width: window.innerWidth, height: window.innerHeight});
18+
useEffect(() => {
19+
const onResize = () => setSize({width: window.innerWidth, height: window.innerHeight});
20+
window.addEventListener('resize', onResize);
21+
return () => window.removeEventListener('resize', onResize);
22+
}, []);
23+
return size;
4824
}
4925

50-
const mapStateToProps = state => state;
51-
const dispatchToProps = dispatch => ({dispatch});
52-
53-
export default connect(mapStateToProps, dispatchToProps)(App);
26+
const App = () => {
27+
const dispatch = useDispatch();
28+
const {width, height} = useWindowSize();
29+
30+
useEffect(() => {
31+
dispatch(wrapTo('map1', addDataToMap({datasets: sampleData, config})));
32+
}, [dispatch]);
33+
34+
return (
35+
<div style={{position: 'absolute', width: '100%', height: '100%'}}>
36+
<button onClick={() => dispatch(wrapTo('map1', hideAndShowSidePanel()))}>
37+
Hide / Show Side Panel
38+
</button>
39+
<KeplerGl mapboxApiAccessToken="pk.xxx.yyy" id="map1" width={width} height={height - 30} />
40+
</div>
41+
);
42+
};
43+
44+
export default App;

examples/custom-reducer/src/configurations/config.js

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,9 @@ export default {
120120
isSplit: false
121121
},
122122
mapStyle: {
123-
styleType: 'light',
124-
topLayerGroups: {
125-
label: true
126-
},
127-
visibleLayerGroups: {
128-
label: true,
129-
road: true,
130-
border: false,
131-
building: true,
132-
water: true,
133-
land: true
134-
}
123+
styleType: 'dark-matter',
124+
topLayerGroups: {},
125+
visibleLayerGroups: {}
135126
}
136127
}
137128
};

0 commit comments

Comments
 (0)