# HINTS TO USE CARTO AND AIRSHIP IN REACT created by Jabal Logian @w3yu2Di_T6-vNOV6L6w63A Instagram, Github, Gitlab, LinkedIn: @jaballogian ## 0. Project Examples 1. [my github project](https://github.com/jaballogian/learn-react-carto-airship) 2. [category widget component](https://github.com/jaballogian/learn-react-carto-airship/tree/master/src/Components/Category%20Widget) 3. [layout examples](https://github.com/jaballogian/learn-react-carto-airship/tree/master/src/Examples) ## 1. Dependencies ### Install necessary dependencies using `npm install` command such as: npm install @carto/airship-components npm install @carto/airship-icons npm install @carto/airship-style npm install @carto/carto.js npm install @carto/carto-vl npm install carto npm install leaflet npm install mapbox-gl npm install react-leaflet ## 2. Index.js file ### Erase React Strict Mode in the `index.js` file (inside src folder) Before: ```javascript= ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') ); ``` After: ```javascript= ReactDOM.render( <App />, document.getElementById('root') ); ``` ## 3. Index.html file ### If want to use mapbox map, add this line of code in the `index.html` file (inside public folder) inside `<head>` tag ```htmlembedded= <link href='https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css' rel='stylesheet' /> <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.0.0/mapbox-gl.css" rel="stylesheet" /> ``` ### If want to use carto map, add these line of codes in the `index.html` file (inside public folder) inside `<head>` tag ```htmlembedded= <link href="https://carto.com/developers/carto-js/examples/maps/public/style.css" rel="stylesheet"></link> <link href="https://carto.com/developers/carto-vl/v1.4.4/examples/maps/style.css" rel="stylesheet"> ``` ### If want to use leaflet map, add these line of codes in the `index.html` file (inside public folder) inside `<head>` tag ```htmlembedded= <link href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" rel="stylesheet"> ``` ## 4. React Functional Component ### 4.1 Create react functional component ```javascript= import React from 'react' function ComponentName(){ return(<div></div>) } export default ComponentName ``` ### 4.2 Import Carto and Airship libraries (css, icons, and components) ```javascript= import '@carto/airship-style/dist/airship.css' import '@carto/airship-icons' import { defineCustomElements } from '@carto/airship-components/dist/loader' defineCustomElements(window) ``` ### 4.3 Import mapbox map library in react component file if want to use mapbox map ```javascript= import mapboxgl from 'mapbox-gl' ``` ### 4.3 If want to use carto map, import carto map library in react component file ```javascript= import L from 'leaflet' import carto from '@carto/carto.js' ``` ## 5. HTML code section ### 5.1 Copy HTML codes from Carto/Airship documentation (included starting and closing `<body>` tags) and paste them inside `return()` of react functional component created Documentation: ```htmlembedded= <body class="as-app-body as-app"> ..... copy everything including the "body" tags </body> ``` Your react component: ```javascript= function ComponentName(){ return( ..... paste the code here ) } ``` ### 5.2 Change HTML code to HTML-in-JS code For example Before: ```htmlembedded= <input type="checkbox" name="checkbox-0"> <hr> ``` After: ```htmlembedded= <input type="checkbox" name="checkbox-0"/> <hr/> ``` ### 5.3 Change all "class" props to "className" props For example Before: ```htmlembedded= <body class="as-app-body as-app"></body> ``` After: ```htmlembedded= <body className="as-app-body as-app"></body> ``` ### 5.4 Change `<style="property1: value1; property2: value2, .....">` props to `style={{property1: "value1", property2: "value2", .....}}` For example Before: ```htmlembedded= <a style="position: absolute; right: 12px; top: 12px;">Close</a> ``` After: ```htmlembedded= <a style={{position: "absolute", right: "12px", top: "12px"}}>Close</a> ``` ### 5.5 Change `id="id-name"` props to `ref={idName}` (from useRef() hook) props if you want to control component For example Before: ```htmlembedded= <button id="js-button-modal"> ``` After: ```htmlembedded= <button ref={jsButtonModal}> ``` ### 5.6 Change `for` props to `htmlFor` props For example Before: ```htmlembedded= <label for="first">First</label> ``` After: ```htmlembedded= <label htmlFor="first">First</label> ``` ### 5.7 Change `tabindex` props to `tabIndex` props For example Before: ```htmlembedded= <ul tabindex="-1"></ul> ``` After: ```htmlembedded= <ul tabIndex="-1"></ul> ``` ### 5.8 Change `readonly` props to `readOnly` props For example Before: ```htmlembedded= <input readonly/> ``` After: ```htmlembedded= <input readOnly/> ``` **Don't forget to read for all error props messages in the browser console and fix them** ## 6. CSS section ### 6.1 Copy CSS codes from Carto/Airship documentation (inside `style` tags) and paste them inside react functional component created Documentation: ```htmlembedded= <style> ..... copy everything inside "style" tags </style> ``` Your react component: ```javascript= function ComponentName(){ ..... paste the code here } ``` ### 6.2 Create constant variable for each styling element and change to CSS-in-JS convention (from `property-name: value;` to `propertyName: "value"`) For example Documentation: ```htmlembedded= <style> as-infowindow { position: absolute; top: 30px; left: 30px; } .as-map-area { background-color: #B5E0F9; } </style> ``` Your react component: ```javascript= function ComponentName(){ const asInfowindow = { position: "absolute", top: "30px", left: "30px" } const asMapArea = { backgroundColor: "#B5E0F9" } return(<div></div>) } ``` **Don't forget to implement the style using the `style={styleName}` prop in the component opening tag** For example ```htmlembedded= <div style={asMapArea}></div> ``` ## 7. JavaScript section ### 7.1 Copy JavaScript code from Carto/Airship documentation (inside `script` tags) and paste them inside react functional component created Documentation: ```htmlembedded= <script> ..... copy everything inside "script" tags </script> ``` Your react component: ```javascript= function ComponentName(){ ..... paste the code here } ``` ### 7.2 Replace `document.querySelector()` method using `useRef()` hook from `react` dependency Import `useRef()` from `react` dependency ```javascript= import {useRef} from 'react' ``` For example Before: ```javascript= var rangeSliderWidget = document.querySelector('as-range-slider') ``` After (put directly inside functional component): ```javascript= function ComponentName(){ const rangeSliderWidget = useRef() } ``` **Don't forget to add `ref={variableName}` props to component opening tag** For example ```htmlembedded= <as-range-slider ref={rangeSliderWidget}></as-range-slider> ``` ### 7.3 Add `.current` to all `useRef` variables For example Before: ```javascript= rangeSliderWidget.minValue = 10 ``` After: ```javascript= rangeSliderWidget.current.minValue = 10 ``` ### 7.4 Use `useEffect()` hook from `react` dependency to load data for all components after rendering them Import `useEffect()` from `react` dependency ```javascript= import {useEffect} from 'react' ``` For example Before: ```javascript= function onLoad () { feedRangeSlider(); feedDropdown(); feedHistogram(); feedCategories(); setModal(); }; ``` After: ```javascript= useEffect(() => { feedRangeSlider() feedDropdown() feedHistogram() feedCategories() }, []) ``` ### 7.5 Create stand alone function to handle on click button For example Before: ```javascript= jsButtonModal.addEventListener('click', function() { jsModal.classList.remove('as-modal--hidden'); jsModal.classList.add('as-modal'); }); ``` After: ```javascript= function jsButtonModalOnClick(){ jsModal.current.classList.remove('as-modal--hidden'); jsModal.current.classList.add('as-modal'); } ``` **Don't forget to add `onClick={OnClickFunction}` props in the component opening tag** For example ```htmlembedded= <button ref={jsButtonModal} onClick={jsButtonModalOnClick}> ```