Skip to content

Instantly share code, notes, and snippets.

@rreusser
Last active May 12, 2022 18:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rreusser/e042dbfc9f26c02724244438ebd6c2de to your computer and use it in GitHub Desktop.
Save rreusser/e042dbfc9f26c02724244438ebd6c2de to your computer and use it in GitHub Desktop.
Ricky's react template

Ricky's React Template

This gist represents my personal hello-world approach to a simple react-based demo page. It's a bit opinionated in the particular sense that I've come to mistrust a lot of third party tools since I often spend more time debugging them than trying to understand the underlying web technologies. Similarly, sooner or later when you use tools like TypeScript or JSX, there's a moment when you realize you're not actually writing JavaScript. Suddenly you can't paste code into the browser console. You can't send it to another JS environment without rewriting. You can't use that one special tool you need because it has to be fully compatible with the build pipeline which pulls in ten other tools you don't.

That's the basis for my opinions. The result is that I've strived hard to iron out an environment that's as ergonomic as create-react-app with React and JSX, but which avoids the need for any tooling or bundler.

Tools I like

  • htm: Like JSX but with JS-native tagged template literals so that you can write ergonomic HTML but keep your JavaScript striclty valid.
  • ES Modules: ES modules resolve import statements without a bundler! You can finally use browser technologies to write plain HTML projects with proper structure and organization! Very cool! Bundling is still necessary for production in order to minify and deliver optimal code but the time when we need bundling for development is limited!
  • unpkg.com: A CDN for serving the plain content of NPM modules. It's very reliable. You will need to invoke Mapbox GL or use React as a global, but I think that's a small price to pay for the simplicity. A really nice trick is to add /browse/ to the root of the URL in order to browse a module's content, e.g. https://unpkg.com/browse/react@18.1.0/.
  • st: A super simple static file server. The CLI gets you off the ground, and if you use the API version, you can extend it with arbitrarily complicated things via http.createServer, like to generate and serve arbitrary map tiles.

Getting started

To start the project in this repo, you only need a static file server. (Note that the package.json is only used to install and start the static file server. The code has no local npm-installed dependencies. External libraries are fetched from unpkg.com, though you could copy the files into your local directory if you don't want to load external resources).

Thus you can just install the static file server and load the page:

npm install
npm start

Then open http://localhost:8000/.

const { useRef, useState, useEffect } = React;
export default function App() {
const mapContainer = useRef(null);
const map = useRef(null);
const [lng, setLng] = useState(-70.9);
const [lat, setLat] = useState(42.35);
const [zoom, setZoom] = useState(9);
useEffect(() => {
if (map.current) return; // initialize map only once
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/mapbox/streets-v11',
center: [lng, lat],
zoom: zoom
});
});
useEffect(() => {
if (!map.current) return; // wait for map to initialize
map.current.on('move', () => {
setLng(map.current.getCenter().lng.toFixed(4));
setLat(map.current.getCenter().lat.toFixed(4));
setZoom(map.current.getZoom().toFixed(2));
});
});
return html`
<div>
<div className="sidebar">
Longitude: ${lng} | Latitude: ${lat} | Zoom: ${zoom}
</div>
<div ref=${mapContainer} className="map-container" />
</div>`;
}
<!doctype html>
<html>
<head>
<script src="https://unpkg.com/react@18.1.0/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18.1.0/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/htm@3.1.1/dist/htm.js"></script>
<script src="https://unpkg.com/mapbox-gl@2.8.2/dist/mapbox-gl.js"></script>
<link rel="stylesheet" href="https://unpkg.com/mapbox-gl@2.8.2/dist/mapbox-gl.css">
<link rel="stylesheet" href="./styles.css">
</head>
<body>
<div id="root"></div>
<script type="module">
window.html = htm.bind(React.createElement);
window.mapboxgl.accessToken = 'YOUR_ACCESS_TOKEN_HERE';
import App from './app.js';
ReactDOM.render(html`<${App}/>`, document.getElementById('root'));
</script>
</body>
</html>
{
"name": "rickys-react-template",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "st --host localhost --port 8000 --no-cache --index index.html"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"st": "^3.0.0"
}
}
.map-container {
height: 400px;
}
.sidebar {
background-color: rgba(35, 55, 75, 0.9);
color: #fff;
padding: 6px 12px;
font-family: monospace;
z-index: 1;
position: absolute;
top: 0;
left: 0;
margin: 12px;
border-radius: 4px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment