Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/yujhenchen/nearby-places-react-leaflet-overpass-api
A finding nearby places app built with React, Vite, Flowbite, Tailwind CSS, leafletjs, React Leaflet, Overpass API, zustand, and TypeScript
https://github.com/yujhenchen/nearby-places-react-leaflet-overpass-api
flowbite front-end frontend leafletjs netlify openstreetmap overpass-api react react-leaflet tailwind-css typescript vite zustand
Last synced: 2 months ago
JSON representation
A finding nearby places app built with React, Vite, Flowbite, Tailwind CSS, leafletjs, React Leaflet, Overpass API, zustand, and TypeScript
- Host: GitHub
- URL: https://github.com/yujhenchen/nearby-places-react-leaflet-overpass-api
- Owner: yujhenchen
- License: mit
- Created: 2023-09-02T10:14:07.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-06-06T15:19:55.000Z (7 months ago)
- Last Synced: 2024-07-30T21:09:55.519Z (5 months ago)
- Topics: flowbite, front-end, frontend, leafletjs, netlify, openstreetmap, overpass-api, react, react-leaflet, tailwind-css, typescript, vite, zustand
- Language: TypeScript
- Homepage: https://jen-nearby-places-react-vite.netlify.app/
- Size: 8.31 MB
- Stars: 5
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Project Features and Issues
A finding nearby places app built with React, Vite, Flowbite, Tailwind CSS, leafletjs, React Leaflet, Overpass API, zustand, and TypeScript.
Table of Contents
- Completed Features
- To-Do Tasks
- Packages Used
- Issues Encountered and Solutions
- Extra Features
- Reference
## Completed Features:
1. Utilized React Query for efficient data fetching and caching, enhancing performance.
2. Expanded categories of places for more comprehensive search options.
3. Implemented storage of the user's current position for enhanced user experience.
4. Added loading UI during data queries for better visual feedback.
5. Enabled single click navigation to any location worldwide directly on the map.
6. Incorporated onScroll events to dynamically adjust card container styles.
7. Implemented functionality to scroll into the corresponding card after clicking on a marker.## To-Do Tasks:
- Pass Refs to Child Components using forwardRef.
- Implement deep refs forwarding for complex component structures.
- Utilize useRef to store a list of elements efficiently.
- Add custom attributes to div elements for enhanced styling flexibility.
- Create custom hooks for map-related functionalities.
- Explore testing React components using Vitest.## Packages Used:
- Flowbite
- Tailwind CSS
- Leafletjs
- React Leaflet
- Overpass API
- Zustand
- React Query## Issues Encountered and Solutions
### 'require' is not defined
In tailwind.config.js on `plugins: [require("flowbite/plugin")],`
**Solution**
ignore eslint```
// eslint-disable-next-line no-undef
plugins: [require("flowbite/plugin")],
```### Flex col auto wrap child element
**Solution**
Change the parent layout to `lg:inline-block` instead of `lg:flex-col`### Overflow scroll does not work when flex row
**Solution**
Add missing width: 100vw; `w-screen` to the flex container### Flex nowrap does not work when flex row
**Solution**
Add missing height `h-full` to the flex element### Default scroll looks ugly
**Solution**
https://www.npmjs.com/package/tailwind-scrollbar### react-leaflet does not show correctly on the page
**Solution**
https://leafletjs.com/examples/quick-start/
does not workhttps://www.npmjs.com/package/react-leaflet?activeTab=dependencies
does not workhttps://stackoverflow.com/questions/40365440/react-leaflet-map-not-correctly-displayed
https://leafletjs.com/examples/quick-start/
it works### Add link and script and width and height
Add the below codes into **index.html**
```
```
```
```Add below codes into **src\App.css**
```
.leaflet-container {
width: 100wh;
height: 100vh;
}
```### Default map is on the top of every component
**Solution**
https://wordpress.org/support/topic/leaflet-map-z-index-and-css/Add the style `z-index: 0 !important;` to the leaflet container class `.leaflet-container` in **src\App.css**
Change the order of components, make leaflet container component to be the first render component. For example, in **src\App.tsx**, where `` is the component that includes leaflet container:
```
import "./App.css";
import MapLayout from "./MapLayout";
import Navigation from "./Navigation";
import ResultContainer from "./ResultContainer";function App() {
return (
);
}export default App;
```In **src\MapLayout.tsx**
```
import React from "react";
import CurrentLocationButton from "./CurrentLocationButton";
import { MapContainer, Marker, Popup, TileLayer } from "react-leaflet";export default function MapLayout() {
return (
A pretty CSS3 popup.
Easily customizable.
);
}
```### Error: `Argument of type 'LatLng' is not assignable to parameter of type 'SetStateAction'. Type 'LatLng' provides no match for the signature '(prevState: null): null'.`
**Solution**
Change `useState(null);` to `useState(null);`## Tasks
### Get the user's current location and mark it on the map
https://react-leaflet.js.org/docs/example-events/
https://stackoverflow.com/questions/66500181/how-to-locate-react-leaflet-map-to-users-current-position-and-get-the-borders-f
Add onClick event to the custom go to current location button `onClick={() => setGoToCurrentPosition(true)}`, to change the state `const [goToCurrentPosition, setGoToCurrentPosition] = useState(false);`
Monitor the state change in the `LocationMarker` component. And add the condition in the `useEffect`, only go to the current location when the state variable `goToCurrent` is true.
Full codes:
```
import { LatLng } from "leaflet";
import { useEffect, useState } from "react";
import {
MapContainer,
Marker,
Popup,
TileLayer,
useMap,
} from "react-leaflet";
import CurrentLocationIcon from "./CurrentLocationIcon";type Props = {
goToCurrentPosition: boolean;
};function LocationMarker({ goToCurrentPosition }: Props) {
const [position, setPosition] = useState(null);const [goToCurrent, setGoToCurrent] = useState(false);
const map = useMap();
useEffect(() => {
setGoToCurrent(goToCurrentPosition);
}, [goToCurrentPosition]);useEffect(() => {
if (goToCurrent) {
map.locate().on("locationfound", function (e) {
setPosition(e.latlng);
map.flyTo(e.latlng, map.getZoom());
});
}
}, [goToCurrent]);return position === null ? null : (
You are here
);
}export default function MapLayout() {
const [goToCurrentPosition, setGoToCurrentPosition] = useState(false);return (
A pretty CSS3 popup.
Easily customizable.
setGoToCurrentPosition(true)}
>
);
}
```### List 10 restaurants near the current location
https://opensource.com/article/18/5/how-build-your-first-gis-app
https://www.npmjs.com/package/query-overpass
https://codesandbox.io/s/b7olo?file=/src/service/overpass.ts
### Try out overpass api on Postman
#### Url
https://overpass-api.de/api/interpreter
#### Method
POST
#### Header
`Content-Type: application/x-www-form-urlencoded;charset=UTF-8`
#### Request body
Query Castles
```
[out:json];(way[historic=castle](around:10000, 50.0874654,14.4212535);
relation[historic=castle](around:10000, 50.0874654,14.4212535););
out body;>;out skel qt;
```Query schools
```
[out:json];
(node[amenity=school](around:10000, 50.0874654,14.4212535););
out body;>;out skel qt;
```### Save the current position for sharable use
Use zustand
### Show restaurants on the map
Change the icons
https://codesandbox.io/s/react-leaflet-icon-material-mx1iu?file=/src/index.js### Get distance information from the current position in km
https://www.geodatasource.com/developers/javascript
### Change the corresponding restaurant card style after clicking the marker
Add `eventHandlers` in `Marker`
```
...{
onClickMarker(e);
},
}}
>
{text}
...
```
In the handler function, set the state variable using the selected position from the event object
```
...const [selectedPosition, setSelectedPosition] = useState(
null
);...
function onClickCustomMapMarker(event: LeafletMouseEvent): void {
setSelectedPosition({ lat: event.latlng.lat, lon: event.latlng.lng });
}...
```
Render the selected card component if the position matches the position of the selected marker
```
...export default function PlaceContainer({
currentPosition,
places,
selectedPosition,
}: Props) {
if (places.length > 0) {
return (
{places.map((place) =>
selectedPosition !== null &&
selectedPosition.lat === place.lat &&
selectedPosition.lon === place.lon ? (
) : (
)
)}
);
} else {
return null;
}
}
```## Extra Features
### Use React Query for efficient data fetching and caching to increase performance
#### Update and pass queryKey for query
https://github.com/TanStack/query/discussions/3200
...
zustand### Edit data after calling API
https://github.com/TanStack/query/discussions/530
...
useMemo### Single chick on the map go to anywhere in the world
https://stackoverflow.com/questions/66288089/how-to-display-a-list-of-points-using-dbclick-in-react-leaflet-v-3-x
### onScroll events for changing card container styles
...
### Scroll into the card after clicking on the corresponding marker
#### Pass Refs to Child Components using forwardRef
https://dmitripavlutin.com/react-forwardref/
https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/forward_and_create_ref/
#### Deep refs forwarding
https://dmitripavlutin.com/react-forwardref/#4-deep-refs-forwarding
...
#### Storing an list of elements using useRef
Possible solution: passing ref as props
https://stackoverflow.com/questions/66764686/how-to-pass-a-ref-down-more-than-one-level-in-reacthttps://eliaslog.pw/how-to-add-multiple-refs-to-one-useref-hook/
Grand child component:
```
...{
if (element) cardRefs.current[index] = element;
}}
key={place.id}...
```...
### Add custom attribute to div
#### XXX does not exist on type 'DetailedHTMLProps, HTMLDivElement>'
Solution
https://stackoverflow.com/questions/46215614/property-does-not-exist-on-type-detailedhtmlprops-htmldivelement-with-react...
### Create custom hooks
https://www.freecodecamp.org/news/how-to-create-react-hooks/
```
const [showStart, setShowStart] = useState(false);const [showEnd, setShowEnd] = useState(true);
```...
### TypeScript: define the return type of the custom hook to be an array with multiple types
https://stackoverflow.com/questions/29382389/defining-array-with-multiple-types-in-typescript
...
## Reference
https://github.com/othneildrew/Best-README-Template