How to use the service locator pattern in SPFx React solutions

How to use the service locator pattern in SPFx React solutions

A couple of months ago, I wrote a blog post on How to get started with React for building advanced SPFx solutions. In that blog post, I told you all the important things you need to be aware of when you start building your very first SPFx solution with React. That included telling you a couple of things when it comes to using the resources available via the SPFx context:

  • You should not pass down the entire SPFx context to your React component, but instead only the objects you truly need.
  • If your project is anything but extremely simple, don’t even pass down some of the objects. Use the service locator pattern instead.

I did not elaborate on how to implement the service locator pattern at that point; the blog post was already over 4000 words long. Instead, I directed you to take a look at one Github project that showed you an example of how you can do it.

Looking back, the example I provided wasn’t necessarily the best one out there. I figured I should instead break it down for you in a separate blog post. And here we are! In this blog post, I’ll show you how you can implement the service locator pattern the right way, so you don’t need to pass down any objects to your child components to be able to use the resources from the SPFx context.

Implementing the service locator pattern

The purpose of the service locator pattern is to allow us to use things like the MSGraphClient or AadHttpClient in our React components. Those are only available when referencing the web part context, which again is only available in the web part/extension file. It is not available for us automatically inside our React components.

The easy way to give our React component access to these resources is to pass them down to the component as props. However, if your solution is big and the architecture is deep, it will become challenging to maintain.

A better way to offer our React components a chance to consume these resources is to create a service. We create a service class and then reference the methods in that class from our components. And we do not need to pass down a reference to the service when we do the following:

  • We initialize the service (singleton) in the onInit() lifecycle method of our web part/extension.
  • We make all the methods in the service class static, so we can use them from anywhere without a class instance.

Initializing the service

Here is an example of a straightforward service that uses the HttpClient object from the SPFx context. What I have here are:

  • A static class property for storing the HttpClient object. It will get its sustained value when we initialize the service.
  • A method that initializes the service. We will call this from our web part file’s onInit method.
  • A static method we can later call from our React components. It will make a GET request by using the HttpClient object that was stored in the static property when we initialized the service.
import { HttpClient } from '@microsoft/sp-http';

export default class HttpService {

  private static httpClient: HttpClient;

  public static Init(httpClient: HttpClient) {
    this.httpClient = httpClient;
  }

  public static async Get(url: string): Promise<any> {
    var response = await this.httpClient.get(url, HttpClient.configurations.v1);
    return await response.json();
  }
}

Here is the onInit() lifecycle method from my SPFx web part file. We call the initialization method of the service class and pass it the HttpClient object from the SPFx context. The HttpClient will get saved to the static property of the service from where it can later be used when we call the static functions of the service.

import HttpService from './services/HttpService'; 

...

protected async onInit(): Promise<void> {
    HttpService.Init(this.context.httpClient);
}

Consuming the service

Now all that is left is to consume the service methods from a React component. It is similar to using any other static class. All we need to do in our React component is:

  • Add an import reference for gaining access to the service class.
  • Call the static methods offered by the service.
import HttpService from '../../services/HttpService'; 

... 

var response = await HttpService.Get(url); 

...

And that is all there is to it!

Afterword

The service locator pattern can seem like a lot of extra hassle at first — especially if you are just getting started with React. However, once you grasp how to do it, it will make your life building SPFx solutions with React so much easier.

I always use the service locator pattern these days, no matter how small my solution is. You never know if the solution will get developed further and grow in the future. And once you know how to do it, it doesn’t take that long to implement. It is a matter of minutes, which is always worth investing in, in my opinion.

I hope you enjoyed reading this article. If you are new to using React with SPFx, make sure you also check out my earlier blog post about How to get started with React for building advanced SPFx solutions.

I’d also love to chat with you on social media. You can find links to all of my profiles in the sidebar or down below for mobile.

Other than that, thank you for reading, and until next time!

Laura



12 thoughts on “How to use the service locator pattern in SPFx React solutions”

  • Dear Laura,

    Great content!! It was very helpful with my SPFx project. Would you please explain even about react-redux with SPFx. It would be really helpful.

    Regards,
    Priya

  • Nice! I will follow this advice. You are good at explaining things & generous to actually share your knowledge. I appreciate it very, very much!

  • Dear Laura,

    Thx a lot for sharing your knowledge through this great and easy to unterstand article! i had to learn spfx/react from scratch for my master thesis project and your blog post helped me a lot to get startet with it.

    Simon

  • Laura – this is fantastic. I started dropping the context through my react components and my code started feel wrong. Why pass all those bits around and constantly re instantiate what should really be a singleton.

    Looking for exactly this solution – thanks so much.

  • Laura,
    you are having a static member of private static httpClient: HttpClient in the class, which you are setting from a static method to store it and to use in a static method later which basically will turn it into an instance variable.
    Will this work in TypeScript, to have an instance variable which will be used without creating one?
    Haven’t tryed it with TypeScript but C# won’t let me do this.
    Anyway, I really enjoy your posts regarding React.

    Greetings
    Thomas

    • Hi Thomas, How can it be turned into an instance variable if no instance is created?

      B.t.w, very nice article Laura. Well explained as always!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.