<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>redux | Kate Gable</title>
	<atom:link href="https://www.katesky.com/tag/redux/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.katesky.com</link>
	<description>sharing knowledge, encouraging to learn, promoting passion for coding, supporting mothers who code</description>
	<lastBuildDate>Sun, 02 Aug 2026 02:25:31 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1</generator>
<site xmlns="com-wordpress:feed-additions:1">193364748</site>	<item>
		<title>Angular NGRX enabling DevTools at runtime</title>
		<link>https://www.katesky.com/2020/06/22/angular-ngrx-enabling-devtools-at-runtime/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=angular-ngrx-enabling-devtools-at-runtime</link>
		
		<dc:creator><![CDATA[Katerina Gable]]></dc:creator>
		<pubDate>Mon, 22 Jun 2020 20:51:26 +0000</pubDate>
				<category><![CDATA[angular]]></category>
		<category><![CDATA[devtool]]></category>
		<category><![CDATA[ngrx]]></category>
		<category><![CDATA[redux]]></category>
		<guid isPermaLink="false">https://www.katesky.com/?p=169</guid>

					<description><![CDATA[<p>Angular NGRX enabling DevTools at runtime ( new version here) In this article, I will cover a problem that I was working on in one of my projects. With help from the NGRX team, I was able to solve it.&#160; Shot-out to <br /><a href="https://www.katesky.com/2020/06/22/angular-ngrx-enabling-devtools-at-runtime/" class="more-link">Read More</a></p>
The post <a href="https://www.katesky.com/2020/06/22/angular-ngrx-enabling-devtools-at-runtime/">Angular NGRX enabling DevTools at runtime</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading">Angular NGRX enabling DevTools at runtime ( new version <a href="https://www.katesky.com/2026/08/02/angular-22-ngrx-enabling-store-devtools-at-runtime-the-modern-way/" title="">here</a>)</h2>



<p class="wp-block-paragraph">In this article, I will cover a problem that I was working on in one of my projects. With help from the NGRX team, I was able to solve it.&nbsp; Shot-out to <a href="https://twitter.com/brandontroberts">@brandontroberts</a> , <a href="https://twitter.com/tim_deschryver">@tim_deschryver</a>, <a href="https://twitter.com/AlexOkrushko">@AlexOkrushko</a>!</p>



<p class="wp-block-paragraph">I hope it helps you when using NGRX, and you can also add it as part of your development process.&nbsp;</p>



<h3 class="wp-block-heading">Problem:</h3>



<p class="wp-block-paragraph">I wanted to be able to enable DevTools at runtime. The reason I want to do that is to be able to let users report his/her application experience and especially the problems they are experiencing.&nbsp;</p>



<p class="wp-block-paragraph">In other words, enable debugging reporting on the fly using NGRX framework.</p>



<h3 class="wp-block-heading">Solution:</h3>



<p class="wp-block-paragraph">This article will be useful if you love Redux DevTools, but you don&#8217;t have them enabled in Production.</p>



<p class="wp-block-paragraph">You would like to have your application to be able to switch to the reporting mode, even in Production.</p>



<p class="wp-block-paragraph">I will cover the following steps:</p>



<ol class="wp-block-list">
<li class="">Adding a lazy-loaded Feature Module</li>



<li class="">Dispatching an effect to create a StoreDevtoolsModule at runtime</li>



<li class="">Extras:
<ol class="wp-block-list">
<li class="">Use hidden F1 key to enable a link for debugging. </li>



<li class="">Enable third party logging/debugging tools  </li>
</ol>
</li>
</ol>



<h3 class="wp-block-heading">Implementation:</h3>



<p class="wp-block-paragraph">We start by adding a feature; we will call it &#8216;debug&#8217;.&nbsp;&nbsp;</p>



<p class="wp-block-paragraph">It will contain:</p>



<ol class="wp-block-list">
<li class=""> debug.action &#8211; We will use an NGRX action from this file to dispatch from the component.</li>



<li class="">debug.component. We will use Debug component to load our feature via a new route we will add to app.module. </li>



<li class="">debug.module &#8211; We will lazy-load this module that in the app.module, and it will contain a route to the component</li>



<li class="">app.module &#8211; Register a new feature with a lazy-loaded route</li>



<li class="">dev-tools.module &#8211; Module that will inject the StoreDevTools to kick-of the Redux tools registration from this module.</li>



<li class="">debug.effect &#8211; We will use this NGRX effect to catch an action dispatched. This effect will be responsible for the runt-time enabling of the dev tools.</li>



<li class="">root-store.module &#8211; Register new Effect in RootModule</li>



<li class="">app.componet &#8211; Add a hiddent button that can be turned visible by F1- hot key</li>
</ol>



<h4 class="wp-block-heading">debug.action.ts</h4>



<p class="wp-block-paragraph">Add a new action to be dispatch to the store about the state change. </p>



<p class="wp-block-paragraph">We prefix the type of the action with the name of the page that will dispatch this action. </p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [3]; title: ; notranslate">
import { createAction } from &#039;@ngrx/store&#039;;

export const enableDebug = createAction(&#039;&#x5B;Debug Page] enable&#039;);
</pre></div>


<h4 class="wp-block-heading">debug.component.ts</h4>



<p class="wp-block-paragraph">Add a new component. If you like, you can keep template and styles inline. Both are not used in this setup, so can easily be excluded. </p>



<p class="wp-block-paragraph">I have an empty template because its not needed.</p>



<p class="wp-block-paragraph">When component is loaded it will dispatch an action that will enable DevTools (line 14).  Effect is below, I promise!</p>



<p class="wp-block-paragraph"><strong>in terminal:</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
ng generate component debug--inlineTemplate=true --inlineStyle=true
</pre></div>


<p class="wp-block-paragraph"><strong>in new file debug.component.ts</strong>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [14]; title: ; notranslate">
import { Component, OnInit } from &#039;@angular/core&#039;;
import { Store } from &#039;@ngrx/store&#039;;
import { RootState } from &#039;../+state/root.selectors&#039;;
import { enableDebug } from &#039;./debug.actions&#039;;

@Component({
  template: ``,
  selector: &#039;app-debug&#039;
})
export class DebugComponent implements OnInit {
  constructor(private readonly store: Store&lt;RootState&gt;) {}

  ngOnInit(): void {
    this.store.dispatch(enableDebug());
  }
}

</pre></div>


<h4 class="wp-block-heading">debug.module.ts</h4>



<p class="wp-block-paragraph">This module is lazy-loaded so it will be registering the child routes.</p>



<p class="wp-block-paragraph"><strong>debug.module.ts</strong>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [6]; title: ; notranslate">
import { NgModule } from &#039;@angular/core&#039;;
import { DebugComponent } from &#039;./debug.component&#039;;
import { RouterModule } from &#039;@angular/router&#039;;
@NgModule({
  imports: &#x5B; 
      RouterModule.forChild(&#x5B;{ path:&#039;&#039;,component:DebugComponent}])
  ],
  declarations: &#x5B;DebugComponent],
  exports: &#x5B;DebugComponent]

})
export class DebugModule {
  constructor(){}
}

</pre></div>


<h4 class="wp-block-heading">app.module.ts</h4>



<p class="wp-block-paragraph">This module we will add a new route and lazy-load it with a feature module. </p>



<p class="wp-block-paragraph">This is a code-snipet , so if you want to see full code check out my repository.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [4,5,6]; title: ; notranslate">
{
    path: &#039;debug&#039;,
    loadChildren: () =&gt;
    import(&#039;./debug/debug.module&#039;).then(
      m =&gt; m.DebugModule
    )
      
  },
</pre></div>


<h4 class="wp-block-heading">dev-tools.module.ts</h4>



<p class="wp-block-paragraph">This module will be compiled and created in the effect. </p>



<p class="wp-block-paragraph">On line 14th you can refresh the tools. I didn&#8217;t see much of a difference in value having it execute.</p>



<p class="wp-block-paragraph"></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [13,16]; title: ; notranslate">
import { NgModule } from &#039;@angular/core&#039;;
import { StoreDevtoolsModule, StoreDevtools } from &#039;@ngrx/store-devtools&#039;;
@NgModule({
  imports: &#x5B;
    StoreDevtoolsModule.instrument({
      maxAge: 25, // Retains last 25 states
      logOnly: true
    })
  ]
})
export class DevToolsModule {
  constructor(private storeDevtools: StoreDevtools) {
    // storeDevtools.refresh();
  }
} 

</pre></div>


<h4 class="wp-block-heading">debug.effect.ts</h4>



<p class="wp-block-paragraph">Effect class is responsible for reacting to the action dispatched from the component.  It filters out actions that it is subscribing to and when enableDebug is dispatched, effect is using &#8216;exhaustMat&#8217; operator to make sure that if same action is dispatched it will continue to execute. In other words dropping incoming request.</p>



<p class="wp-block-paragraph">Next it uses injected compiler object to compile dev-tools.module and creates it on lines 21-24.</p>



<p class="wp-block-paragraph">Once that is completed, we have devtools enabled and redux tools can be used to track our state changes.</p>



<p class="wp-block-paragraph">We know that we will have a manual mechanism of turning debugging option on so we can redirect our user back to that location. In this case it&#8217;s root of the application or home. So the changeLink action is returned via this effect.</p>



<p class="wp-block-paragraph"></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [21,22,23,24]; title: ; notranslate">
import { Injectable, Compiler, Injector } from &#039;@angular/core&#039;;
import { createEffect, Actions, ofType } from &#039;@ngrx/effects&#039;;

import * as DebugActions from &#039;./debug.actions&#039;;
import { exhaustMap } from &#039;rxjs/operators&#039;;
import { DevToolsModule } from &#039;./dev-tools-module&#039;; 
import { changeLink } from &#039;../+state/root.actions&#039;;

@Injectable()
export class DebugEffects {
  constructor(
    private actions$: Actions,
    private compiler: Compiler,
    private injector: Injector
  ) {}

  debugAction$ = createEffect(() =&gt;
    this.actions$.pipe(
      ofType(DebugActions.enableDebug),
      exhaustMap(async () =&gt; {
        const m = this.compiler.compileModuleSync&lt;DevToolsModule&gt;(
          DevToolsModule
        );
        m.create(this.injector); 
        return changeLink({ link: &#039;&#039; });
      })
    )
  );
}

</pre></div>


<p class="wp-block-paragraph">If you checkout my repository you will see that I just imported DevToolsModule into the DebugModule for simplicity. I kept the effect for other use case in Extra#2.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [8]; title: ; notranslate">
import { NgModule } from &#039;@angular/core&#039;;
import { DebugComponent } from &#039;./debug.component&#039;;
import { RouterModule } from &#039;@angular/router&#039;;
import { DevToolsModule } from &#039;./dev-tools-module&#039;;
@NgModule({
  imports: &#x5B; 
      RouterModule.forChild(&#x5B;{ path:&#039;&#039;,component:DebugComponent}]),
      DevToolsModule
  ],
  declarations: &#x5B;DebugComponent],
  exports: &#x5B;DebugComponent]

})
export class DebugModule {
  constructor(){}
  
}

</pre></div>


<h4 class="wp-block-heading">app.component.html</h4>



<p class="wp-block-paragraph">Add anywhere you would like to include a hidden button. So next time your user is having some unexplainable issues they can hit F1 and it will become visible.</p>



<p class="wp-block-paragraph">Can you tell I am using material components?  So if you this code make sure you import all necessary Modules for Material <a href="https://material.angular.io/components/button/api" target="_blank" rel="noreferrer noopener">here</a>.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; title: ; notranslate">
&lt;button *ngIf=&quot;isDebugVisible&quot; (click)=&quot;onDebug()&quot;mat-icon-button aria-label=&quot;debug&quot;&gt;
  &lt;mat-icon&gt;bug_report&lt;/mat-icon&gt;
&lt;/button&gt;
</pre></div>


<h4 class="wp-block-heading">app.component.ts</h4>



<p class="wp-block-paragraph">Extra #1: As promised I will give this little trick. I added hidden button to help user discover issues and be part of the debugging process.</p>



<p class="wp-block-paragraph">We will add a function to make our button visible with HostListener, filtering out keys. </p>



<p class="wp-block-paragraph">Next we will add a button click event that will redirect our user to the lazy-loaded module we just setup.  </p>



<p class="wp-block-paragraph"><strong>Remember</strong>: user will be redirected back here from the debug.effect? </p>



<p class="wp-block-paragraph">So we can turn off the button &#8211; our devtools are enabled!</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
  onDebug() {
    this.store.dispatch(changeLink({ link: &#039;debug&#039; }));
    this.isDebugVisible = false;
  }
  @HostListener(&#039;document:keydown&#039;, &#x5B;&#039;$event&#039;])
  keypress(e: KeyboardEvent) {
    if (e.key === &#039;F1&#039;) {
      this.isDebugVisible = true;
    }
  }
</pre></div>


<h4 class="wp-block-heading">Extras #2</h4>



<p class="wp-block-paragraph">If you haven&#8217;t heard of LogRocket yet. Let me Introduce you. <a href="http://www.logrocket.com">www.logrocket.com</a> This is a very cool product that you can plugin to the application to see a full path of your user experience with visual snap shots.</p>



<p class="wp-block-paragraph">How cool is that?</p>



<p class="wp-block-paragraph">If you follow their instruction it is pretty straight forward to include and get started with in your application.</p>



<p class="wp-block-paragraph"><strong> https://app.logrocket.com/&lt;replace-with-yourcode&gt;/settings/integrations/</strong></p>



<p class="wp-block-paragraph">It is a paid product, if you exceed the number of requests that are free! </p>



<p class="wp-block-paragraph">But let see if we can utilize a free version by only enabling the setup from our debug lazy-loaded module dev-tools.module? </p>



<p class="wp-block-paragraph"><strong>update debug.effect.ts</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [7,26]; title: ; notranslate">
import { Injectable, Compiler, Injector } from &#039;@angular/core&#039;;
import { createEffect, Actions, ofType } from &#039;@ngrx/effects&#039;;

import * as DebugActions from &#039;./debug.actions&#039;;
import { exhaustMap } from &#039;rxjs/operators&#039;;
import { DevToolsModule, LOGROCKET_INIT_KEY } from &#039;./dev-tools-module&#039;;
import * as LogRocket from &#039;logrocket&#039;; 
import { changeLink } from &#039;../+state/root.actions&#039;;

@Injectable()
export class DebugEffects {
  constructor(
    private actions$: Actions,
    private compiler: Compiler,
    private injector: Injector
  ) {}

  debugAction$ = createEffect(() =&gt;
    this.actions$.pipe(
      ofType(DebugActions.enableDebug),
      exhaustMap(async () =&gt; {
        const m = this.compiler.compileModuleSync&lt;DevToolsModule&gt;(
          DevToolsModule
        );
        m.create(this.injector);
        LogRocket.init(LOGROCKET_INIT_KEY);
        return changeLink({ link: &#039;&#039; });
      })
    )
  );
}

</pre></div>


<p class="wp-block-paragraph"><strong>update dev-tool.module.ts</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [3,4,5,6,7,8,9,10,11,12,13,14,15,16,24,25,26,27,28,29,30,31]; title: ; notranslate">
import { NgModule } from &#039;@angular/core&#039;;
import { StoreDevtoolsModule, StoreDevtools } from &#039;@ngrx/store-devtools&#039;;
import { USER_PROVIDED_META_REDUCERS } from &#039;@ngrx/store&#039;;
import * as LogRocket from &#039;logrocket&#039;;
import createNgrxMiddleware from &#039;logrocket-ngrx&#039;;
import { MetaReducer, State } from &#039;@ngrx/store&#039;; 
import { RootState } from &#039;../+state/root.selectors&#039;;
const logrocketMiddleware = createNgrxMiddleware(LogRocket, {});

export const metaReducers: MetaReducer&lt;any&gt;&#x5B;] = &#x5B;];

export function getMetaReducers(): MetaReducer&lt;RootState&gt;&#x5B;] {
  return metaReducers.concat(&#x5B;logrocketMiddleware]);
}
export const LOGROCKET_INIT_KEY = &#039;&lt;replace-with-your-code&#039;;

@NgModule({
  imports: &#x5B;
    StoreDevtoolsModule.instrument({
      maxAge: 25, // Retains last 25 states
      logOnly: true
    })
  ],
  providers: &#x5B;
  
    {
      provide: USER_PROVIDED_META_REDUCERS,
      useFactory: getMetaReducers
    }
  ]}
)
export class DevToolsModule {
  constructor(private storeDevtools: StoreDevtools) {
    // storeDevtools.refresh();
  }
}

</pre></div>


<p class="wp-block-paragraph">Now that we have this setup, we can see our requests are only feeding into our LogRocket account after we enabled debug!</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">I hope you enjoyed this article! Tweet you questions or comments <a rel="noreferrer noopener" href="https://twitter.com/intent/tweet?text=Hi,@katesky8 &quot;Question/comment about your post Angular NGRX enabling DevTools at runtime 👍👍👍&amp;url=https://www.katesky.com/2020/06/22/angular-ngrx-enabling-devtools-at-runtime" target="_blank">here</a>. </p>



<p class="wp-block-paragraph">I will be glad to connect too!</p>



<p class="wp-block-paragraph"></p>



<ul class="wp-block-social-links is-layout-flex wp-block-social-links-is-layout-flex">



<li class="wp-social-link wp-social-link-twitter wp-block-social-link"><a href="https://twitter.com/intent/tweet?text=Hi,@katesky8%20Question/comment%20about%20your%20post%20Angular%20NGRX%20enabling%20DevTools%20at%20runtime%20👍👍👍&#038;url=https://www.katesky.com/2020/06/22/angular-ngrx-enabling-devtools-at-runtime" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M22.23,5.924c-0.736,0.326-1.527,0.547-2.357,0.646c0.847-0.508,1.498-1.312,1.804-2.27 c-0.793,0.47-1.671,0.812-2.606,0.996C18.324,4.498,17.257,4,16.077,4c-2.266,0-4.103,1.837-4.103,4.103 c0,0.322,0.036,0.635,0.106,0.935C8.67,8.867,5.647,7.234,3.623,4.751C3.27,5.357,3.067,6.062,3.067,6.814 c0,1.424,0.724,2.679,1.825,3.415c-0.673-0.021-1.305-0.206-1.859-0.513c0,0.017,0,0.034,0,0.052c0,1.988,1.414,3.647,3.292,4.023 c-0.344,0.094-0.707,0.144-1.081,0.144c-0.264,0-0.521-0.026-0.772-0.074c0.522,1.63,2.038,2.816,3.833,2.85 c-1.404,1.1-3.174,1.756-5.096,1.756c-0.331,0-0.658-0.019-0.979-0.057c1.816,1.164,3.973,1.843,6.29,1.843 c7.547,0,11.675-6.252,11.675-11.675c0-0.178-0.004-0.355-0.012-0.531C20.985,7.47,21.68,6.747,22.23,5.924z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Twitter</span></a></li>







<li class="wp-social-link wp-social-link-twitter wp-block-social-link"><a href="https://twitter.com/KateSky8" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M22.23,5.924c-0.736,0.326-1.527,0.547-2.357,0.646c0.847-0.508,1.498-1.312,1.804-2.27 c-0.793,0.47-1.671,0.812-2.606,0.996C18.324,4.498,17.257,4,16.077,4c-2.266,0-4.103,1.837-4.103,4.103 c0,0.322,0.036,0.635,0.106,0.935C8.67,8.867,5.647,7.234,3.623,4.751C3.27,5.357,3.067,6.062,3.067,6.814 c0,1.424,0.724,2.679,1.825,3.415c-0.673-0.021-1.305-0.206-1.859-0.513c0,0.017,0,0.034,0,0.052c0,1.988,1.414,3.647,3.292,4.023 c-0.344,0.094-0.707,0.144-1.081,0.144c-0.264,0-0.521-0.026-0.772-0.074c0.522,1.63,2.038,2.816,3.833,2.85 c-1.404,1.1-3.174,1.756-5.096,1.756c-0.331,0-0.658-0.019-0.979-0.057c1.816,1.164,3.973,1.843,6.29,1.843 c7.547,0,11.675-6.252,11.675-11.675c0-0.178-0.004-0.355-0.012-0.531C20.985,7.47,21.68,6.747,22.23,5.924z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Twitter</span></a></li></ul>



<p class="wp-block-paragraph">If you would like to see a repository where I added this implementation,  follow this github link: </p>



<p class="wp-block-paragraph"><a href="https://github.com/katesky/saraphan-radio/tree/azure/apps/shell-app/src/app/debug">https://github.com/katesky/saraphan-radio/tree/azure/apps/shell-app/src/app/debug</a> </p>The post <a href="https://www.katesky.com/2020/06/22/angular-ngrx-enabling-devtools-at-runtime/">Angular NGRX enabling DevTools at runtime</a> first appeared on <a href="https://www.katesky.com">Kate Gable</a>.]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">169</post-id>	</item>
	</channel>
</rss>
