MapScreen is finally a functional component so we can save a lot of trouble and use HOOKS
No more deprecated componentWillReceiveProps !!
Lots of helper functions are extracted out to mapUtils or converted to custom hooks so they can be reused in #178
Significant loading speed/UX improvements, especially with the addition of a loading screen (currently a placeholder to be redesigned).
The new MapScreen flow:
useCurrentLocation prompts the user for location access and if granted, it sets the user's location incurrentLocation (otherwise null). Location permission status is saved in locationPermissions as either 'granted', 'denied', or 'error'
useStores loads the list of stores from Airtable, not in any sorted order.
Store distance calculations and sorting happen directly since they are neither async nor expensive. The sorted store list (with the added distance attribute) is passed into StoreListScreen and to other store-related components that reference distance.
Once stores and location permissions are loaded, a useEffect sets the initial currentStore to focus on.
useStoreProducts loads the products for currentStore, refreshing whenever currentStore is updated.
Other misc. changes
findStoreDistance returns null if the store distance is greater than 100 miles (NPO said if the user is >100 miles away, keep the focus in the DC area and treat it as if their location settings are off). This eliminated the need for other things like showDefaultStore and seeDistance being passed around to show/hide store distances since any non-null distance values should be displayed.
Converted StoreListScreen to functional component
Moved ButtonContainer that wrapped around the RewardsFooter into the actual RewardsFooter component
Cleaned up incorrectly used state variables in RewardsFooter and SettingsScreen
How to review
I'll leave some comments in the actual code on particular areas I'm confused about, but in general, I'd appreciate feedback on:
general best practice with hooks -- when/where/how they should be used
ways I could clean up my code, naming conventions, etc.
What's new in this PR
componentWillReceiveProps
!!mapUtils
or converted to custom hooks so they can be reused in #178The new MapScreen flow:
useCurrentLocation
prompts the user for location access and if granted, it sets the user's location incurrentLocation
(otherwisenull
). Location permission status is saved inlocationPermissions
as either 'granted', 'denied', or 'error'useStores
loads the list of stores from Airtable, not in any sorted order.store
list (with the addeddistance
attribute) is passed intoStoreListScreen
and to other store-related components that reference distance.useEffect
sets the initialcurrentStore
to focus on.useStoreProducts
loads the products forcurrentStore
, refreshing whenevercurrentStore
is updated.Other misc. changes
findStoreDistance
returns null if the store distance is greater than 100 miles (NPO said if the user is >100 miles away, keep the focus in the DC area and treat it as if their location settings are off). This eliminated the need for other things likeshowDefaultStore
andseeDistance
being passed around to show/hide store distances since any non-nulldistance
values should be displayed.StoreListScreen
to functional componentButtonContainer
that wrapped around theRewardsFooter
into the actualRewardsFooter
componentRewardsFooter
andSettingsScreen
How to review
Relevant Links
Online sources
https://reactjs.org/docs/hooks-custom.html https://www.robinwieruch.de/react-hooks-fetch-data https://reactjs.org/docs/thinking-in-react.html
Next steps
Screenshots
Here's how it loads AFTER this refactor. SO MUCH FASTER! https://www.loom.com/share/090a25122bcd44a09e5960f2893b083e