DEV Community

Cover image for Debug Ionic Application (NGRX) using Redux remote dev tools
Mohammed Taher
Mohammed Taher

Posted on

Debug Ionic Application (NGRX) using Redux remote dev tools

Recently I was working on Ionic app that was built with Angular. The application uses NGRX for state management. I wanted to debug the state (i.e inspect actions, and state ..etc) while application is running on emulator. I expected that by simply running redux dev tools from chrome that it will magically work out of the box, and straight away, but unfortunately this was not the case.

Looking around for sometime I stumbled upon a precious article that was explaining how to put everything together.

Unfortunately the article is outdated, but through some further search and playing around, I managed to make everything work.

I thought to share details here to help anyone who might be looking for a solution to same exact issue.

  • Step 1:
    install NGRX store dev tools

  • Step 2:
    Create 2 files to handle connection between your application and Redux remote dev tool

File1:
remote-devtools-connection.ts

import { ReduxDevtoolsExtensionConnection } from '@ngrx/store-devtools/src/extension'

export class RemoteDevToolsConnectionProxy implements ReduxDevtoolsExtensionConnection {
  constructor(public remotedev: any, public instanceId: string) {}
  init(state?: any): void {
    console.log('Socket was initiated', state)
  }
  error(anyErr: any): void {
    console.error('Socket Error', anyErr)
  }

  subscribe(listener: (change: any) => void): any {
    const listenerWrapper = (change: any) => {
      listener(change)
    }

    this.remotedev.subscribe(listenerWrapper)
    // Hack fix for commit/time-travelling etc. if the devtools are already open
    setTimeout(() => listenerWrapper({ type: 'START' }))
  }

  unsubscribe(): any {
    // HACK fix bug in @ngrx/store-devtools that calls this instead of returning
    // a lambda that calls it when their Observable wrapper is unsubscribed.
    return () => this.remotedev.unsubscribe(this.instanceId)
  }

  send(action: any, state: any): any {
    this.remotedev.send(action, state)
    // Never called
  }
}

Enter fullscreen mode Exit fullscreen mode

File2 (depends on File1):
remote-devtools-proxy.ts

import {
  ReduxDevtoolsExtension,
  ReduxDevtoolsExtensionConfig,
  ReduxDevtoolsExtensionConnection
} from '@ngrx/store-devtools/src/extension'
import { connect } from 'remotedev/lib/devTools'

import { RemoteDevToolsConnectionProxy } from './remote-devtools-connection'

export class RemoteDevToolsProxy implements ReduxDevtoolsExtension {
  remotedev: any = null
  defaultOptions = {
    realtime: true,
    autoReconnect: true,
    connectTimeout: 20000,
    ackTimeout: 10000,
    secure: true
  }

  constructor(defaultOptions: Object) {
    this.defaultOptions = {
      ...this.defaultOptions,
      ...defaultOptions
    }
    console.log('Socket config', this.defaultOptions)
  }

  connect(
    options:
      | {
          shouldStringify?: boolean
          instanceId: string
        } & ReduxDevtoolsExtensionConfig
  ): ReduxDevtoolsExtensionConnection {
    const connectOptions = Object.assign(this.defaultOptions, options)

    this.remotedev = connect(connectOptions)

    const connectionProxy = new RemoteDevToolsConnectionProxy(
      this.remotedev,
      connectOptions.instanceId
    )
    return connectionProxy
  }

  send(action: any, state: any): any {
    this.remotedev.send(action, state)
  }
}

Enter fullscreen mode Exit fullscreen mode

File3 (depends on File2): make sure to include this file in your app based on your environment setup. Like direct import, or webpack include .. etc

The variables REMOTE_DEV_HOST & REMOTE_DEV_PORT can be environment dependent, or hardcoded. You can hardcode them at least to make sure everything works as expected. However the most important point it to use "EXACT" same IP, and PORT in all following steps

index.ts

import { RemoteDevToolsProxy } from './remote-devtools-proxy'

declare const REMOTE_DEV_HOST: string
declare const REMOTE_DEV_PORT: number

if (!window['devToolsExtension'] && !window['__REDUX_DEVTOOLS_EXTENSION__']) {
  console.log('!!!!!! REDUX INSPECTION HAS STARTED !!!!!')
  const remoteDevToolsProxy = new RemoteDevToolsProxy({
    // Needs to match what you run `remotedev` command with and
    // what you setup in remote devtools local connection settings
    hostname: REMOTE_DEV_HOST,
    port: REMOTE_DEV_PORT,
    connectTimeout: 300000, // extend for pauses during debugging
    ackTimeout: 120000, // extend for pauses during debugging
    secure: false // dev only
  })

  // support both the legacy and new keys, for now
  window['devToolsExtension'] = remoteDevToolsProxy
  window['__REDUX_DEVTOOLS_EXTENSION__'] = remoteDevToolsProxy
} else {
  // handle case outside real device, or emulator
}

Enter fullscreen mode Exit fullscreen mode
  • Step 3: in your angular module make sure you include store dev module
@NgModule({
  imports: [CommonModule, StoreDevtoolsModule.instrument({ maxAge: 100 })]
})
Enter fullscreen mode Exit fullscreen mode
  • Step 4:
    install @redux-devtools/cli

  • Step 5:
    add a script to start redux devtools server which will listen to state, and action changes in your package.json

scripts:
{"remote-dev":"redux-devtools --hostname=ADD_IP_FROM_PREVIOUS_STEPS --port=ADD_PORT_FROM_PREVIOUS_STEPS --wsEngine=ws --logLevel=3"}
Enter fullscreen mode Exit fullscreen mode

and run it in a separate terminal tab/window

  • Step 6: You may get some error about global is not defined, and in this case add following to polyfill.ts (this is generated by default in your root folder) in your Angular app (more info can be found here)

polyfill.ts

(window as any).global = window
Enter fullscreen mode Exit fullscreen mode
  • Step 7: open chrome, and right click redux extension to open remote dev tools

Image description

  • Step 8: connect to your host from redux remote settings (UX is bad as there is no feedbad if connection succeeds, or fails). Howevwer ater successful connection you should see the store visible in your dev tools

Image description

Image description

Happy Hacking ...

Top comments (0)