SJ

Kelp

Business Search Web App Tool

"Search for your favorite coffee shop in real-time with an interactive map view."

Live | GitHub

{name}
Search bar with 3 different "Sort By" options

Project Brief:

Codecademy Pro Capstone
React Project

Role / Skills:

Lead Developer

Technologies Used:

  • React
  • Redux
  • JavaScript
  • SCSS
  • CSS keyframe animations
  • Yelp API
  • Mapbox API
  • CORS Anywhere
  • Single Page Application

Summary:

  • Responsive business search tool created with an interactive Mapbox map view to find businesses from retrieved Yelp API data
  • Client-side fetch of Yelp API endpoints implemented using CORS Anywhere
  • This application started off as a Codecademy Pro React course project that I further developed to have an interactive map experience as well as a responsive, mobile experience.

    The biggest challenges I faced dealt with connecting the map markers to behave according to my vision. I only had access to the Yelp API data of each search result, which gave me the address and coordinates for each business found. I then hooked up that data to Mapbox, and made sure the results and the map markers communicated bi-directionally whenever clicking or pressing on either or.

    How I did it:
    • In my Map component, on the map markers side, whenever you click or press any map marker, I used React-Redux to dispatch an action type of “MARKER_CLICKED” with a payload of marker.properties.id that stored that info in my global Redux state. Using the useEffect() hook in the parent component, this event would trigger the actual business from the search results list to be scrolled into view automatically using the scrollIntoView()method and the DOM manipulation classList.add() method to add highlighting styling to the selected result.

    • In my individual Business component, on the BusinessList side, whenever you click on an image of a business from the search results, it extracts the Yelp coordinates data from that business, sends it back up to the parent component, and then sets the current state of the clickedOnBusiness, and finally sends that back down to the Map component to fly into the actual map marker with the matching coordinates using the Mapbox API's flyTo() method.

    Another challenge I faced was making sure to clear the map markers from previous search results whenever querying for new searches so they wouldn't pile up (the previous map markers did not clear automatically after running a new search). I used the useRef() hook and the .current property to keep track of the current search results data in an array, and compared that array against the next, new search results. If they didn't match, I looped through the current array of existing map markers and removed them in order to empty the array and make room for the new incoming search results.

    mobile-view kelp
    Mobile view of search bar
    kelp MapBox map view
    Map view provided by MapBox API

    Challenges Faced:

    Creating a Custom, Interactive Map

    Using the React Hook, useEffect(), I created a function to toggle an "active" CSS class, adding or removing highlighting styling whenever users click on any map markers. Concurrently, I used scrollIntoView with behavior: "smooth" to effortlessly glide to the business listing of the selected map marker.

    interactive-map kelp
    2-way interactive map!
    Fixed/sticky map that scrolls with you!

    Clearing existing markers from previous searches

    Using the React Hook, useRef() and the .current property, I was able to retrieve the existing array of map markers from the previous search and compare it against the new array of businesses populated by Yelp from running a new search.

    If those two arrays weren't exactly alike, I used the built-in MapBox marker.remove() function to clear all markers from the map.

    if (currentMarkers.current !== businesses) {
            currentMarkers.current.forEach(marker => marker.remove());
      }
    

    Map resizing bug: Required automatic triggering of window-resizing event

    For my map's display/hide toggle, I came across a bug where the Mapbox map displayed inconveniently at 1/4th the container's size when toggling to display. The only way to set the size back to normal was by resizing the window manually.

    In my map toggle button's handleClick function, I included this setTimeout() function to dispatch a window resize trigger event to automatically cause a resize AFTER the map displayed from invisible to visible.

    setTimeout(() => {
          window.dispatchEvent(new Event('resize'))
        }, 0)
    

    Loading JS script into the React project on mount

    In order for the Mapbox API to create and load the map on mount, I had to figure out how to load the Javascript <script> file from a CDN, (as you would normally insert the <script> tag right before the closing <body> tag of an HTML file).

    I used this custom loadScript function that takes in any CDN URL and injects it into the React-rendered HTML page on mount, similarly to placing the <script> tag in the HTML file manually.

    function loadScript(url) {
        const index = window.document.getElementsByTagName("script")[0];
        const script = window.document.createElement('script');
        script.src = url;
        index.parentNode.insertBefore(script, index);
    }
    

    Final Results:

    search for tandoorisearch for juicesearch for ice cream
    Businesses data imported from Yelp API. Search for your favorite bites!