Friday, January 31, 2020

ReactJS - You tried to redirect to the same route you're currently on

It's a common problem when you redirect on same route will give a warning like You tried to redirect to the same route you're currently on: /profile/2. It's because of when we define Route we can not define for every parameters like 1, 2, 3 etc. Normally we define our Route like:

<Route path="/profile/:id" component={Profile} />

And this will handle every URL like http://example.com/profile/1, http://example.com/profile/2 etc.
But sometimes when we use Redirect component to redirect to another profile page from current profile page using the below code

return <Redirect to={"/profile/" + this.state.id} push={true} />;

The above warning thrown because our Route is same for all URL like /profile/1 as well as /profile/2.
To avoid this warning we need to define key to our Route like below

<Route path="/profile/:id" render={props => { return <Profile {...props} key={props.match.params.id} />; }} />
Full example is created on CodeSandbox.IO https://codesandbox.io/s/you-tried-to-redirect-to-the-same-route-youre-currently-on-063ot

Thursday, January 2, 2020

Request Mocking In Grails For Back-end/Background Threads | Mock Request With Session

Request Mocking In Grails For Back-end/Background Threads | Mock Request With Session

package com.pkm.util

import grails.gsp.PageRenderer
import grails.util.Holders
import org.codehaus.groovy.grails.web.servlet.mvc.GrailsHttpSession
import org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest
import org.springframework.web.context.request.RequestContextHolder

import javax.servlet.ServletContext
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpSession
/**
 * Created by pritom on 16/08/2017.
 */
class HibernateRequestUtils {
    static GrailsWebRequest getRequest() {
        return RequestContextHolder.getRequestAttributes()
    }

    static HttpSession getSession() {
        return request?.session
    }

    static void setValueToSession(String key, def value) {
        session.putAt(key, value)
    }

    static def getValueFromSession(String key) {
        return session.getAt(key)
    }

    static boolean isBound() {
        HttpServletRequest.isBound()
    }

    static boolean hasSession() {
        session != null
    }

    static def mock(Closure closure = null) {
        return HttpServletRequest.mock(closure)
    }

    static {
        HttpServletRequest.metaClass.static.with {
            isBound = {
                RequestContextHolder.requestAttributes != null
            }
            mock = { closure = null ->
                HttpServletRequest _request = PageRenderer.PageRenderRequestCreator.createInstance("/page/dummy")
                _request.IS_DUMMY = true
                _request."javax.servlet.include.servlet_path" = "/page/dummy.dispatch"
                GrailsWebRequest webRequest = new GrailsWebRequest(
                        _request,
                        PageRenderer.PageRenderResponseCreator.createInstance(new PrintWriter(new StringWriter())),
                        Holders.servletContext
                ) {
                    private MockedHttpSession _session

                    MockedHttpSession getSession() {
                        if (this._session == null) {
                            this._session = new MockedHttpSession()
                        }
                        return this._session
                    }
                }
                RequestContextHolder.setRequestAttributes(webRequest)
                if (closure) {
                    def returned = closure()
                    RequestContextHolder.resetRequestAttributes()
                    return returned
                }
                return webRequest
            }
        }
    }
}

class MockedHttpSession extends GrailsHttpSession {
    MockedHttpSession() {
        super(null)
    }

    private LinkedHashMap attributes = [:]

    Object getAttribute(String name) {
        attributes[name]
    }

    Enumeration getAttributeNames() {
        Collections.enumeration(attributes.keySet())
    }

    long getCreationTime() {
        0
    }

    long getLastAccessedTime() {
        0
    }

    int getMaxInactiveInterval() {
        0
    }

    ServletContext getServletContext() {
        return Holders.servletContext
    }

    @Deprecated
    String[] getValueNames() {
        [] as String[]
    }

    @Deprecated
    void putValue(String name, Object value) {}

    @Deprecated
    void removeValue(String name) {}

    void invalidate() {}

    boolean isNew() {true}

    void removeAttribute(String name) {
        attributes.remove(name)
    }

    void setAttribute(String name, Object value) {
        attributes[name] = value
    }

    void setMaxInactiveInterval(int arg0) {}
}


And use be like below:


if (HibernateRequestUtils.isBound()) {
    DO YOU CODE IN HTTP REQUEST
}
else {
    HibernateRequestUtils.mock {
        DO YOUR CODE IN MOCK REQUEST AS YOU DO IN REAL REQUEST
    }
}



Using Google Place Autocomplete API in React

I want to have an auto completing location search bar in my react component
Reference Google Maps API JS library via /public/index.html file:
Get google API Key from here -> https://developers.google.com/places/web-service/get-api-key
https://cloud.google.com/console/google/maps-apis/overview
You need to enable Maps JavaScript API & Places Api from below links ->
https://console.developers.google.com/google/maps-apis/apis/maps-backend.googleapis.com

https://console.developers.google.com/google/maps-apis/apis/places-backend.googleapis.com

import React from "react";

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.autocompleteInput = React.createRef();
    this.autocomplete = null;
    this.handlePlaceChanged = this.handlePlaceChanged.bind(this);
  }

  componentDidMount() {
    this.autocomplete = new google.maps.places.Autocomplete(
        this.autocompleteInput.current, {"types": ["geocode"]}
    );

    this.autocomplete.addListener('place_changed', this.handlePlaceChanged);
  }

  handlePlaceChanged(){
    const place = this.autocomplete.getPlace();
    this.props.onPlaceLoaded(place);
  }



  render() {
    return (
        <input ref={this.autocompleteInput}  id="autocomplete" 
         placeholder="Enter your address"
         type="text"></input>
    );
  }
}

export default MyComponent

Wednesday, January 1, 2020

bootstrap-datepicker with React: onChange doesn't fire while onClick does

bootstrap-datepicker with React: onChange doesn't fire while onClick does
import React, { Component } from 'react'
import {Redirect} from "react-router-dom";

class MyComponent extends Component {
    constructor () {
        super();
        this.state = {
     back: false,
            dateOfBirth: "",
            dateOfBirthInput: ""
        };
        this.handleUserInput = this.handleUserInput.bind(this);
    }

    componentDidMount () {
        super.componentDidMount();

        $(this.state.dateOfBirthInput).datepicker({
     format: "mm/dd/yyyy"
 });

        $(this.state.dateOfBirthInput).on('changeDate', function(e) {
            console.log(e);
            console.log(e.target.value);
     this.handleUserInput(e);
        })
    }

    handleUserInput (e) {
        let name = e.target.name;
        let value = e.target.value;

        console.log(`Name=${name}, value=${value}`);

        this.setState({[name]: value});
    }

    render () {
        if (this.state.back) {
            return <Redirect to={'/dashboard/user-profile'} push={true}/>
        }
        return (
            <div>
                <div className="form-group row">
                    <label className={'col-12 col-sm-12 col-md-4 col-lg-3 col-xl-2 col-form-label'}>Date of birth</label>
                    <div className="col-12 col-sm-12 col-md-8 col-lg-9 col-xl-10">
                        <div className='input-group date'>
                            <input name={'dateOfBirth'} value={this.state.dateOfBirth}
                                   onChange={(e) => this.handleUserInput(e)}
                                   ref={(n) => this.state.dateOfBirthInput = n}
                                   type='text' className="form-control"/>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

export default MyComponent