Skip to content

Commit

Permalink
feat: common Hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael2Gray committed Feb 11, 2022
1 parent d3f543f commit eb54352
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export * from './use-context-fallback.hook';
export * from './use-geolocation.hook';
export * from './use-mounted.hook';
export * from './use-timeout.hook';
15 changes: 15 additions & 0 deletions src/hooks/use-context-fallback.hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Context, useContext } from 'react';

export const useContextFallback = <T>(value: Context<T | undefined>): T => {
const context = useContext<T | undefined>(value);

if (context === undefined) {
throw new Error(
`Components that require this context must be children of ${
value.displayName ?? 'the appropriate provider'
}.`
);
}

return context;
};
23 changes: 23 additions & 0 deletions src/hooks/use-geolocation.hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useEffect, useMemo, useState } from 'react';

import { Coordinates } from '../models';

export const useGeoLocation = (): Coordinates | null => {
const [geoLocation, setGeoLocation] = useState<Coordinates | null>(null);

useEffect(() => {
navigator.geolocation.getCurrentPosition(
({ coords }) => setGeoLocation(coords),
() => setGeoLocation(null),
{
enableHighAccuracy: false,
timeout: 60000,
}
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const value = useMemo(() => geoLocation, [geoLocation]);

return value;
};
16 changes: 16 additions & 0 deletions src/hooks/use-mounted.hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useCallback, useEffect, useRef } from 'react';

export const useMounted = () => {
const mountedRef = useRef(false);
const isMounted = useCallback(() => mountedRef.current, []);

useEffect(() => {
mountedRef.current = true;

return () => {
mountedRef.current = false;
};
}, []);

return isMounted;
};
1 change: 1 addition & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ import './style.css';
export * from './components';
export * from './hooks';
export * from './models';
export * from './utils';
35 changes: 35 additions & 0 deletions src/utils/distance.util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Coordinates } from '../models';

/**
* Distance calculation based on the Haversine formula
* Credit: https://stackoverflow.com/a/21623206/12130423
* @param coordsA - The coords of the users location (geoCoords or defaultCoords)
* @param coordsB - The coords of the city
*
* @returns Distance in km (number) to two decimal places
*/
export const getDistanceBetweenCoords = (
coordsA: Coordinates,
coordsB: Coordinates
): number => {
const R = 6371.071; // Radius of the Earth in miles
const coordsALatRad = coordsA.latitude * (Math.PI / 180); // Convert degrees to radians
const coordsBLatRad = coordsB.latitude * (Math.PI / 180); // Convert degrees to radians
const latDiff = coordsBLatRad - coordsALatRad; // Radian difference (latitudes)
const lonDiff = (coordsB.longitude - coordsA.longitude) * (Math.PI / 180); // Radian difference (longitudes)

const distance =
2 *
R *
Math.asin(
Math.sqrt(
Math.sin(latDiff / 2) * Math.sin(latDiff / 2) +
Math.cos(coordsALatRad) *
Math.cos(coordsBLatRad) *
Math.sin(lonDiff / 2) *
Math.sin(lonDiff / 2)
)
);

return Number(parseFloat(String(distance)).toFixed(2));
};
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './distance.util';

0 comments on commit eb54352

Please sign in to comment.