Skip to content
Chris Marx edited this page Sep 28, 2021 · 48 revisions

Welcome to the foss4g-2021-react-mapbox wiki!

Setup

  1. Git clone the blank repo

  2. Setup create react app blank project - add link

    cd foss4g-2021-react-mapbox
    #NOTE you could use a "." to build in the current folder, but we actually will need this to be in it's own project folder
    npx create-react-app deck-layers-map --template typescript
    
  3. Add the dependency for react-map-gl - add link

    npm install react-map-gl
    
  4. Start by create a map component. Autogenerate the component with this https://github.com/arminbro/generate-react-cli:

    npx generate-react-cli component BackdropMap
    

    We're using typescript, react testing library, stories, stylesheets with sass, etc.

  5. In general, it's a good idea to not name your components with the same name as built in classes in Javascript, so typically you should avoid naming things "Map", "Set", "Array", "WeakMap", "Date" etc. - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects, it will give you odd errors, and will make it so you have to alias your classes if you want to also use those things in your app.

  6. Then we want to be using the open source fork of mapbox, so follow the instructions here https://visgl.github.io/react-map-gl/docs/get-started/get-started and install:

    npm i maplibre-gl
    

    Note that i is just short for install, and if you ever used --save or -S in the past, you don't need that any longer since it's automatic. You do still need --save-dev or -D for dev dependencies. For maplibre, we mainly need to follow those instructions, but unfortunately they aren't complete. The css import from mapbox has been renamed, so we have to use the new name not the old one, because the filename itself has changed. There is also an issue with mapbox/maplibre and transpilation which they note here: ---link---- Annoyingly, those exact instructions didn't work for me. When using react, angular, vue, the clis are also using webpack under the hood, and one thing webpack does is transpilation (es6 - es5). However, even leaving our app at ES6 with browserlist isn't enough for this esoteric issue with mapbox and webworkers. This is what worked for me.

  7. Except that the very next step is add a one liner to your webpack config. Unfortunately, unless you want to add craco (which is totally fine), there's no way to configure apps created by created-react-app without "ejecting". Ejecting just lifts the covers from your eyes, and all the complexity of properly building, bundling, testing, etc is revealed. [HERE SHOW PICTURE OF JS ENGINEERS CONFIGURING WEBPACK]. Ejecting isn't so bad though, especially for a smaller project that you might not ever really need to upgrade to all the latest and greatest features and depenendencies automatically. Plus, we will building most of this app not using create-react-app, so the code within this project will be minimal.

  8. With the basics working, it's time to move our project to codesandbox.io, along with stackblitz and a few others, these online IDEs are really useful and learning to use them is a good idea, because if you ever run into problems with your app, your chances are a 1000x better that someone will actually help or diagnose the problem for you on stackoverflow or even in github (if it's really a bug in the js libraries). They remove the issue of "it only does/doesn't work on my machine".

  9. And bonus, the first thing we see is that the compass control icon is missing. If you want a more seamless development experience, you should probably stick with mapbox proper, but we're at FOSS4G, so we are going to trudge forward and find the fix, and while we're at it, we can comment on the issue in the repo, with a codesandbox example and explanation for a fix. If we were really adventurous, we could make a PR, but this is probably enough for now, lol:

    https://github.com/visgl/react-map-gl/issues/1467
    
  10. As our first foray into components, we could customize the navigation control, and add a custom buttom for resetting the viewport. At this point, to really make have our micro-frontend component driven design shine, we're actually going to create a whole different project, that will serve purely as a library for our components.

  11. You said Typescript though, why. I recommend programming in Typescript because it's like having a friend help you code, it's like not coding in the dark. Typescript catches your errors as you're making them, rather than once you've actually run your program, and given that in large application, plenty of the app doesn't all run at startup, it also finds the errors that you won't encounter until you visit that particular section of your application. It also gives you a lot of visibility into what is actually happening when you're passing in or returning values, and easily links you to documentation. I'll show examples of all of these as we go through the creation of our app today. Lastly, I'd say that Typescript attempts to only demand the smallest modicum of additional code, and does as much as possible to not have you spending time on types. It will however, force you to actually understand the basics of the language, because the errors will be incomprehensible if you don't understand arrays, objects, etc.

Creating a side panel component with data layers

  1. Ok, let's make this map more interesting.

    npm install deck.gl
    

    Deck.gl is an extension for visualizations using mapbox, also open source from Uber. However, the first we find when trying to use this in our project is that vscode doesn't seem to recognize the library at all. That's because the project hasn't officially released it's typings yet. When developing, you'll typically find many projects that were already written in typescript, so the typings are there already, the typings are contained in the package, so you don't need to do anything extra, or you'll get a message like this:

    Could not find a declaration file for module 'my-untyped-module'. '.../node_modules/my-untyped-module/index.js' implicitly has an 'any' type.
    Try `npm install @types/my-untyped-module` if it exists or add a new declaration (.d.ts) file containing `declare module 'isomath';`  TS7016
    

    Often, the types are usually available from the @types package repo, which can contain user-submitted types for libraries as well. In thi case, a quick google search reveals they haven't even made it there yet, but they do exist:

    https://github.com/danmarshall/deckgl-typings

Moving components to a reusable library

  1. Everything we've done up until now is just fine for this project, but if you wanted to use any of the components we've created in another react app, you'd have to copy and paste those files into the new project. That defeats a lot of the point for component driven design. If you're building a lot of maps, you want one set of reusable peices, and if you update them, you at least want the option to update multile projects as well.

  2. Unfortunately, out of the big three (angular, react, vue), react is the only project without a standardized cli that is capable of scaffolding a new react library project. Which is really disappointing, and I think we should all be making noise about this. So, this will involve a bit more manual setup that our initial project, but it's still worth it.

  3. Steps

    • mkdir rmg-component-lib && cd rmg-component-lib
    • npm init
    • npm i -D typescript
    • touch tsconfig.json - and add tsconfig contents
    • Add peer dependencies
    • npm i -D react-dom react @types/react-dom @types/react
    • npm link ../deck-layers-map/node_modules/react
    • npm init
    • npm init
  4. Now let's add material ui, since it's an easy place to start for building apps

    • npm i -D @mui/material @emotion/react @emotion/styled
    • npm install -D @mui/icons-material
    • We can look for a component at material-ui, like the drawer, and first just open the codesandbox and see if we can easily adapt it for our needs, and it looks like it can. We can move the button to the main section, get rid of the top header, and we can customize the component to accept the content for the "Main" area through transclusion (angular word, but basically using composition of components).
    • Then we can add it to our project, and it basically works, remove some padding, add some styles, switch to a floating action button, etc. We also need to improve our build scripts, because now we want tsc and copyfiles running at the same time, so add nodemon and exec:
    • npm install --save-dev nodemon
    • npm install --save-dev copyfiles
    • Then add build scripts and combine them to run whenever nodemon detects changes
  5. For our layer panel, we can use the example here to power a basic form selection:

Typescript

  1. We're going to see where typescript helps us all over the app, but an easy place to show it would be added props to a component, but failing to supply the React.FC definition, since otherwise props.* is an error, because we don't actually know what we're getting

1.Here's another good one, using useState but forgot to destructure? That'll throw a nice error to remind you of what you did wrong.

Clone this wiki locally