Migrating a realtime Checkins Discovery App from React to Preact
Tags: react, foursquare, googlemaps, preact
Published: 2018-09-04 11:41:36

---
title: Migrating a realtime Checkins Discovery App from React to Preact
published: true
description: Comprehensive Migrating a realtime Checkins Discovery App from React to Preact
tags: reactjs, foursquare, googlemaps, preact
---

In this post we are going to create a client side web application to render FourSquare Checkins of a specified location per user's preference in realtime. The major technologies we are going to use is ReactJS, FourSquare API, Google Maps API.

And later down the tutorial we will see how to migrate a pre-written react app to a preact app.

## Overview

React-Checkins is a realtime checkins discovery app built using Google Maps API with ReactJS.

Once rendered the app looks as below

![Alt text of image](https://blog.apcelent.com/images/preact-react-app.png)

## Setup and Maps Integration

We will use npm for managing all our code dependencies. First let’s setup npm in the root of our project. This will generate a file called *package.json* in project root. If you use the --save or --save-dev flag when installing a package, it’ll save the packages as dependencies in the package.json file. To reinstall the packages, all we need to is run npm install. The packages will be installed locally specific to our project under a directory called node_modules like virtualenv.

So, let’s generate a package.json file in our project root using npm init.

```python
npm init
```

Let’s install our first npm packages.

npm install --save react webpack babel babel-loader webpack-dev-server react-google-maps react-addons-update classnames

package.json contains several other dependencies.

npm should install the dependencies under the node_modules folder structure by default.

## Create webpack config

Let us now create a webpack config. The goal of creating the config file is to concatenate all the js files.

```python
mkdir -p src/js
touch webpack.config.js
touch dev/js/components/GoogleApp.js
```

Let’s create a simple webpack config to load .jsx files using babel and [More on webpack configuration here.](https://github.com/webpack/docs/wiki/contents)

webpack.config file

```python
var path = require('path');
var webpack = require('webpack');


module.exports = {
    devServer: {
        inline: true,
        contentBase: './src',
        port: 3000
    },
    devtool: 'cheap-module-eval-source-map',
    entry: './dev/js/components/GoogleApp.js', ///entry point of our app. 
    module: {
        loaders: [
            {
                test: /\.js$/,
                loaders: ['babel'],
                exclude: /node_modules/
            },
            {
                test: /\.scss/,
                loader: 'style-loader!css-loader!sass-loader'
            }
        ]
    },
    output: {
        path: 'src',
        filename: 'js/bundle.min.js'
    },
    plugins: [
        new webpack.optimize.OccurrenceOrderPlugin()
    ]
};
```

At this point, our directory structure will look something like this.

```python
root
  |-- dev
    | |--js
    |     |--components
    |         |--GoogleApp.js
    |-- node_modules
    |-- src
    | |-- js
    |   | |-- bundle.min.js   ## will create after run npm start
    |   |-- index.html
    |-- webpack.config.js
    |-- package.json
    |-- .babelrc
```

The index file is fairly simple and can be found [here](https://github.com/apcelent/preact-reactjs/blob/master/src/index.html)

## Initializing Maps in React Component

```python
Import {
    withGoogleMap,
    GoogleMap,
    Marker,
    InfoWindow,
 } from "react-google-maps";
```

If you're going to be loading the map through your index.html file you can include the below.

```python
 <script src="https://maps.googleapis.com/maps/api/js?key=GOOGLE_API_KEY&callback=initMap&libraries=places"async defer></script>
```

### Dynamically retrieving the Google Maps Library

```python
const GettingStartedGoogleMap = withGoogleMap(props => (
    <GoogleMap
    ref={props.onMapLoad}
    defaultZoom={3}
    options={{ minZoom: 3, maxZoom: 15 }}
    center={{ lat: 20.5937, lng: 78.9629 }}
    >
    {props.markers.map(marker => (
        <Marker
          { ...marker }
          onRightClick={() => props.onMarkerRightClick(marker)}
          onMouseOver={() => props.onMouseOver(marker)}
          >
          {marker.showInfo && (
            <InfoWindow >
              <div className="">
              {marker.info ?
                <p><b>{marker.info[0].user.firstName} says </b>
                    {marker.info[0].text}</p>
                : null}
                <p><b>Place </b> {marker.key}</p>

                </div>
              </InfoWindow>
            )}

        </Marker>

    ))}
    </GoogleMap>
));
```

### Getting initial state of markers

```python
constructor(props)
        {
            super(props);
            this.state = {
                markers: [{
                    position: {
                        lat: null,
                        lng: null,
                    },
                    key: null,
                    defaultAnimation: null,
                    showInfo:false,
                    info: []
                }],
                address: '',
                results: []
            };
            this.onChange = (address) => this.setState({ address })
        }
```

## Search the places through the foursqaure

The searchNearPlaces function takes the response from the city search query and pushes all the results inside an array object with their respective [lat, lng] co-ordinates and pin’s icon link.

```python
getUrl() {
    const clientID = YOUR_FOURSQUARE_CLIENT_ID,
         clientSecret = YOUR_FOURSQUARE_CLIENT_SECRET,
         version = 'v=20140806';
    let location = this.state.address,
    url = 'https://api.foursquare.com/v2/venues/explore?client_id=' +
      clientID + '&client_secret=' + clientSecret + '&near=' +
        location + '&' + version;
    return url;
}

searchNearPlaces() {
    let url = this.getUrl();
    axios.get(url)
        .then(response => {
            let results = response.data.response.groups[0].items;
            this.setState({ results:results });
            // Do with results

        })
}
```

Let's save the first 20 out of total results as markers.

```python
 var bounds = new google.maps.LatLngBounds();
 results.map((el, i) => {
    if (i < 20 ) {
    const nextMarkers = [
    ...this.state.markers,
    {
    position: {
        lat: el.venue.location.lat,
        lng: el.venue.location.lng  },
    defaultAnimation: 2,
    key: el.venue.name,
    showInfo: false,
    info: el.tips
    },
    ];
    this.setState({
    markers: nextMarkers,
    })

   bounds.extend(this.state.markers[i].position);
   }

})
this._mapComponent.fitBounds(bounds);   // bound the all markers of map
```

And now we render the component

```python
render() {
    const inputProps = {
        value: this.state.address,
        onChange: this.onChange
        type: 'search',
        placeholder: 'Search Places...',
        autoFocus: true,
    }
    const cssClasses = {
        root: 'form-group',
        input: 'form-control',
        autocompleteContainer: 'my-autocomplete-container'
    }
    const myStyles = {
        root: { position: 'absolute' },
        input: { width: '100%' },
        autocompleteContainer: { backgroundColor: 'green' },
        autocompleteItem: { color: 'black' },
        autocompleteItemActive: { color: 'blue' }
    }

    const AutocompleteItem = ({ suggestion }) => (<div>
      <i className="fa fa-map-marker"/>{suggestion}</div>)
    return (
        <div ref="map" style={{height: '600px'}}>
            <Helmet
              title="GoogleMap"
            />
            <form onSubmit={this.handleFormSubmit.bind(this)}>
                <PlacesAutocomplete
                    inputProps={inputProps}
                    classNames={cssClasses}
                    styles={myStyles}
                    autocompleteItem={AutocompleteItem}
                     />
                     <button type="submit">Submit</button>
            </form>


            <GettingStartedGoogleMap
              containerElement={
                 <div style={{ height: '650px' }} />
             }
             mapElement={
                <div style={{ height: '650px' }} />
             }
             onMapLoad={this.handleMapLoad.bind(this)}
             markers={this.state.markers}
             onMouseOver={this.handleOnMouseMarker.bind(this)}

             onMarkerRightClick={this.handleMarkerRightClick.bind(this)}
            />
        </div>
      );
  }
  /// google maps loaded with support of initMap
  window.initMap = () => {
  ReactDOM.render(
      <GettingStartedExample />,
  document.getElementById('root')
  )
}
```

We will now add a funcationality to show the info of a marker on mouse hover

```python
var react_update = require('react-addons-update');


update[index_val] = {
    $merge: {showInfo: false}
   };
   var changedMarkers = react_update(this.state.markers, update);
   this.setState({ markers: changedMarkers });
```

## Replacing ReactJS with PreactJS

Recently Facebook modified the license of ReactJS from BSD to BSD+patents license. Addition of patents clause means that if it felt that the product using ReactJS is competing with facebook, it's license will be revoked. So, we started looking for alternatives of ReacJS which would work seamlessly with existing react application. Preact is one such solution.

Preact is a lightweight javascript library (3 kb) which can be used as a replacement for [Reactjs](https://reactjs.org/)

## Installation

[preact-compat](https://github.com/developit/preact-compat) is another layer on top of preact which allows us to switch from react to preact without much changes to the existing code.

First, install preact and preact-compat modules

```python
npm i --save preact
npm i --save preact-compat
```

To use preact with webpack, we add an alias for react and react-dom in webpack.config.js file

```python
resolve: {
        extensions: ['', '.js', '.jsx'],
        "alias": {
            "react": "preact-compat",
            "react-dom": "preact-compat"
        }
   },
```

In the example, a simple [react hello world application](https://github.com/vibhash1083/react-map-checkins/tree/preact) has been created. It has one component HelloWorld.js

```python
import React, { Component } from 'react';
import ReactDOM from "react-dom";


export default class HelloWorld extends Component {
    constructor(props)
    {
        super(props);
    }


  render()
  {


    return (
          <div>
          <h1>
            Hello World!
            </h1>
          </div>
     );

  }
}

ReactDOM.render(
    <HelloWorld />,
    document.getElementById('root')
)
```

Once the webpack.config.js file is updated to add alias of preact and preact-compat, application works in same way as preact-compat provides same exports as react and react-dom.

```python
var path = require('path');
var webpack = require('webpack');

module.exports = {
    devServer: {
        inline: true,
        contentBase: './src',
        port: 3000
    },
    devtool: 'cheap-module-eval-source-map',
    entry: './dev/js/components/HelloWorld.js',
    module: {
        loaders: [
            {
                test: /\.js$/,
                loaders: ['babel'],
                exclude: /node_modules/
            },
            {
                test: /\.scss/,
                loader: 'style-loader!css-loader!sass-loader'
            }
        ]
    },
    output: {
        path: 'src',
        filename: 'js/bundle.min.js'
    },
    resolve: {
        extensions: ['', '.js', '.jsx'],
        "alias": {
            "react": "preact-compat",
            "react-dom": "preact-compat"
        }
    },
    plugins: [
        new webpack.optimize.OccurrenceOrderPlugin()
    ]
};
```

We used same configuration changes to react map checkin application and the checkin discovery works as before.

## Conclusion

It is a working React-Checkins app providing a fair understanding of how we can integrate Google Maps with (P)ReactJS — all in less than 15 minutes. For reference, the entire code is [here](https://github.com/apcelent/preact-reactjs)

The article originally appeared on [Apcelent Tech Blog.](https://blog.apcelent.com/Migrating-a-realtime-Checkins-Discovery-App-from-React-to-Preact.html)