Thursday, November 9, 2023

Avoid unnecessary re-renders with React Context

React Context provides a way to pass data through the component tree without having to pass props down manually at every level.  However, when using the Context API, it's important to understand how to avoid unnecessary re-renders, which can cause performance issues and slow down the application. In this blog, I will share some tips on how to avoid unnecessary re-renders when using the React Context API.

To avoid unnecessary re-renders when updating the Context in React, you can use the useMemo hook along with the Context Provider. This allows you to memoize the value you pass down through the Context, preventing unnecessary re-renders of consumers.

Here's a step-by-step guide:

    1. 1. Create a Context Provider Component:

    1. First, create a Context and a Provider component. The Provider component will use useMemo to memoize the value provided to the Context.


  1. 2. Wrap Your App with the Provider:

  1. In your main index.js file or the component where your app starts, wrap your app with the Provider:


  1. 3. Consuming Context in Components:
  2. Now, you can consume the Context value using the useContext hook in your components:


  1. By using useMemo, you ensure that the value provided by the Context Provider only changes when the state it depends on changes. This prevents unnecessary re-renders of components that consume this Context.

  2. Remember to replace initialState, newState, and any other placeholder values with your actual application logic.



Friday, April 24, 2020

Iterate two arrays simultaneously with one foreach statement in C#


Let’s say that you have two lists or two arrays that you wish to combine.  One has a list of first names, the other a list of last names.  The list items are in the correct order so that the first name would match the last name for a given ordinal number.  But the lists may not have the same lengths (i.e. one list is not as complete as the other).  We wish to match all of the available first and last names until we run out of matching pairs.

So, what do we do?

For two arrays, we could use a “for int” loop.  We could get the size of each array by calling its Length property. And then we can compare which length is smaller; and use that number as our loop’s upper boundary.  We could then use the indexer to refer to each element in turn.  But this solution is rather inelegant.

For two lists, we should not use a “for int” loop, since lists do not have the concept of indexers.  We cannot refer to individual elements of the list via an index.  We can instead use a “foreach” loop.  But how do you refer to corresponding elements from 2 lists with each loop iteration?

This is where the Linq’s Zip method comes in very handy.  With the Zip method, we can apply a specific function to the corresponding elements of two sequences and produce a sequence of the results.

Using the above scenario as an example, where we have 5 first names but only 4 last names, we can write the following code:


The Output is below.

You will notice that the Zip function stopped after its 4th iteration.  In this way, we don’t have any incomplete names.

That’s it for now.  I hope this tip has been super helpful.



Thursday, October 20, 2016

Angular2 Custom Pipes on Two-Way Bound Input Controls



In my previous blog, I showed you how to create a custom pipe for phone numbers.  If you haven’t read it yet, I recommend that you do so before continuing with this article.  Click here for that blog


The custom pipe works great for formatting data in labels (i.e. one-way bound controls).


But what if you wanted to apply the custom pipe to an input control, and have it bind bi-directionally?  That is, the data from the data model is formatted in the view, and the data entered by the user is automatically validated and formatted as well?  What if you wanted to do something like the code below?


When you run this code, Angular2 will complain and throw a nasty exception like the one below:



The code is failing exactly for the reason that you see in the error message: You cannot use a pipe in an action expression, which is what the two-way binding of the input control is.  Double binding with pipes will not work.  Angular2 does not support it.

So, what do we do then?  Well, I’m glad you asked.

While we cannot do two-way data binding, we can still do one-way bindings.  We can break down what we are trying to do into two one-way data bindings, so that we format on the way out, and validate and format on the way in.  For this trick, we will need to listen to the Angular2 “ngModelChange” event for the input control. 

We filter the “ngModel” through our custom pipe, and we wire up our data model to the “ngModelChange” event.  Our code would now look like this:



Now your input control would exhibit behavior similar to a two-way-bound control, with the benefit of a pipe filter.  That's it.

I’d like to add a bonus tip.  If all you are looking for is to have the phone number formatted a certain way, and you did not want to take the trouble of building a custom pipe, then you can take advantage of HTML5’s new Phone Number Input Type Form Validation. 

This is simply an HTML5 input control with type=”tel” and a pattern attribute with the phone number regular expression that you would like to validate against.  You also have the option of adding a title, which would serve as a “hint” to the user.  It would require your user to comply with the pattern, but it would ensure that the input is valid.  Your markup code would now look like below:


When your user attempts to submit an invalid entry, the user would get a friendly error message and a hint.


And that is how you take advantage of HTML5’s built-in phone number input type form validation.

In this blog, I showed you how to make use of pipes in an input control that is intended to bind both ways.  I also showed an alternative way to validate two-way-bound input controls using HTML5 form validation.

Tuesday, October 18, 2016

Angular2 Custom Pipe for Phone


Angular2 pipes are great for formatting data labels.  And Angular2 already comes with a bunch of built-in pipes out-of-the-box, including the Date Pipe, Decimal Pipe, Currency Pipe, LowerCase and UpperCase Pipes, JSON Pipe, Percent Pipe, Slice Pipe, and Async Pipe.

“Why isn’t there a Pipe for telephone numbers?” you might ask.  Standardizing on phone number formats is notoriously tricky because, with all the different international phone number conventions, there are no standards.  So, if you need a Pipe for phone numbers, you need to build a custom Pipe yourself.  Unfortunately I could not find one on the web, so I wrote one myself.


You will need to import “Pipe” from Angular2 Core, give your new pipe a name, and implement or override the “Transform” function.


As you can see in the code, this Pipe will transform the input by a) stripping out any non-numeric characters, b) take only the first 10 valid characters, and c) apply the area code parenthesis and the hyphen separator.

To consume our Phone Pipe in our component, we would need to a) import the Pipe and b) declare it in the pipes array inside our Component decorator.


In our view, we apply the Phone Pipe as simply as below:


Regardless of the user’s input (entering invalid characters or entering more than 10 characters), the Phone Pipe will format it as you desired.

This Phone Pipe works great when you are just formatting a label.  But what if you wish to format the data in an input control?  Then we are talking about applying pipes to a control with two-way data binding, and that would be much trickier.

In this article, I showed you how to implement a custom Phone Pipe.  In my next blog, I will discuss how you can apply formatting and validation using pipes on an input control.

Sunday, October 16, 2016

NgModel Data Binding and Http Call fails with Undefined properties

I hope that this little tip would help save you the couple of hours that it took me to figure out.

I have an Angular2 component with a View that has two-way data binding to a TypeScript object model.   The component calls a Web API Service to populate and then update this object model.  The TypeScript model in the Angular2 component is identical to the strongly-typed Data Model in the Web API.  But when I subscribe to the Web API Service and then assign its result to my object model, the properties of my object model become “Undefined”.

This is my Angular2 component (abbreviated for brevity):


This is my Angular2 view (abbreviated for brevity):


This is my TypeScript model for the UserAccounts object:


This is my implementation of the "updateUserAccount" service in the Web API, with some Swagger annotations:



This Http PUT operation is returning a data object of type “UserAccount”.

And this is my strongly-typed UserAccount class in my Web API:


As you can see, the data models in the Angular2 client component and the Web API server response are identical. 


In fact, at the "ngOnInit" event handler, the call to the “getUser” service is successful, returning a response of type “UserAccountModel”, and populating the view with the object data accordingly.


This is what the view looks like after “ngOnInit”:

The “Update” event handler is nearly identical.  It makes a call to the “updateUserAccount” service of the Web API, which is an Http PUT verb operation.  The “profileInput” parameter is of type “UserAccountModel”, and the API service return type is also “UserAccountModel”.
However, once execution enters this “Update” event handler, the properties of the “profileInput” object become "Undefined".  Assigning the property values of the return object to the individual properties of the “profileInput” object did not help either.


I have verified that the Web API service was returning a response successfully.  Yet the two-way bound properties of the data object were becoming Undefined.  So what the heck is going on?

It turns out that, unlike the return objects from my Web API’s GET operations, the return objects from my Web API’s PUT operations undergo a quirky transformation.  Specifically the casing of their property names is automatically changed to Pascal Case, so that the first letter of each property name becomes lowercase.

Below is what a similar object would look like in Google’s Developer Tools.  Notice that the property names are in Pascal Case, whereas the derived data model was defined with Camel Case.  That incongruity caused the property assignments to the “profileInput” object in the Angular2 client component to fail.


I had to create a new TypeScript data model that observed this new casing, and use that as the return data type from the Web API call.

Replacing the UserAccountModel with the UserAccountReturnModel as the return type of the “updateUserAccount” service call, everything began to work as expected.
The ngModel two-way data binding does not really have any direct relevance to the quirk with the return object from the Web API, but I did mention it in this article because the symptoms of this issue might be confused with the two-way data binding with the data model during an HTTP call.


In this blog, I showed a “gotcha” when making HTTP service calls and the object types returned from those calls. 


Thursday, December 10, 2015

Word.Application.Documents.Open returns a Null



Okay, so you have embarked on a project that requires dynamically generating Microsoft Office Word documents based on a template Word document. 

Naturally you have already added a Reference to the "Microsoft Word Object Library" to your project, by right-clicking on your project, Adding Reference / COM / Type Libraries / Microsoft Word Object Library.
I have the 15.0 version of the Word object library for my project.

You have written the appropriate C# server-side code to open the document, by using the "Documents.Open" method of the Word.Application object.


 
Everything works in your local development environment.  Hurray for you!
But hold on. 

While everything works in your machine, it fails in the web server you deployed your application to.
You get the error message:
    An exception of type 'System.NullReferenceException' occurred but was not handled in user code.
    Additional information: Object reference not set to an instance of an object.

How can that be?

The answer is that Word failed to open the document because you did not have the proper permissions to do so.
Or rather, the user account which tried to open the Word document did not have appropriate access rights.

Below is the unintuitive solution for you.
Open the Component Services module from the Start Menu, or search for it.
You can manually start it from "C:\Windows\System32\comexp.msc"


In the Component Services window, expand the nodes to Console Root / Component Services / Computers / My Computer / DCOM Config


Under DCOM Config, scroll down to find "Microsoft Word 97 - 2003 Document" or its equivalent in your server.


Right-click on "Microsoft Word 97 - 2003 Document", select Properties / Identity.


In the Identity tab, change the option control selection from "The launching user" to "The interactive user".

Hit OK and Exit. 

And voila! 
Your frustrating error goes away, and your application magically works as you expected in your web server.



Monday, August 31, 2015

The type or namespace name 'Twilio' could not be found


So, you have finally joined the exciting new world of ASP.NET 5. 
Congratulations!  And welcome!

You may be running Visual Studio 2015 - or maybe Visual Studio Code - and creating new DNX projects and ASP.NET 5 applications that target the latest .NET Framework 4.6 or .NET Core 5, running on DNX, and compiling with RyuJIT or the Roslyn platform.
Good for you!

So, let's say that you writing a DNX project that makes use of the Twilio SMS API Client.
If you're reading this blog, then you probably already know that Twilio SMS is an API that lets you programmatically send, receive and track text messages globally.

Your code, in simple terms, will look like the one below


Your logic looks solid. 
You instantiate your Twilio client with your Account Sid and Auth Token, and you invoke the SendMessage service by passing in the appropriate parameters.

So why then, does your build fail and the Error List pane show the error below?


The type or namespace name 'Twilio' could not be found (are you missing a using directive or an assembly reference?)

How can this be? 
You already have the correct Using statement.
And you have already installed the Twilio package through NuGet.

Well, what's happening here can be explained by looking at your "project.json" file.


Here, we see that both the "dnx451" (.Net Framework) and "dnxcore50" (.Net Core 5) are being targeted.
However, .Net Core 5 does NOT support the Twilio SDK.  Ergo the "type or namespace" error.

There are a couple of ways to resolve this issue.
The first is to simply remove the "dnxcore50" from the list of targeted frameworks in the project.json file.


This is a simple and straightforward solution.
However, it does exclude the .NET Core 5 framework from your project altogether, and that may not be your intent.

The second alternative is something of a "shim". 
Using a compiler directive, you can exclude any code that "dnxcore50" does not support.



In this way, you are still targeting the .NET Core 5 framework, but at the same time,
your app does not break on any code that the framework does not support.

Happy .Net coding!