March 11, 2020

Sharing Data Across SPFx Web Parts Using PnP Storage

304 Views
Sharing Data Across SPFx Web Parts Using PnP Storage

Background

Many SharePoint pages need multiple custom SPFx web parts for a useful design. In developing such a page, a developer often encounters a situation when one web part requests the same data from a source where it is already requested by another web part. One can always make an independent call to the same source. Better would be to store the data already received from the source in a place where other web parts can quickly reuse the value.

By sharing data among the web parts directly on the client-side, one can significantly improve the performance of the page simultaneously reducing the network traffic.

This post illustrates a simple catching mechanism using PnP client storage such that the web parts do not need to make API calls if the data is already available fetched by some other web part.

PnP Storage

PnP Storage can essentially store data (e.g. list data) in a common cache. This cache is global and available across web parts. So, once the API is called for the first web part that loads the data on the page; that data may be cached in PnP storage and then it is made available to all the web parts from the cache. Thus independent API calls are avoided across web parts.

Steps to implement PnP Storage:

Add PnP Storage to Service layer:

In the API /service layer this feature needs to be implemented. Look at the following steps.

  • First, we need to import PnPClientStorage module along with other requisites:
    
    import { IListItem } from './IListItem';
    import { PnPClientStorage } from "@pnp/common";
    import pnp, { Web } from 'sp-pnp-js';
    
     
  • Next, we create the ListItemService class which holds the storage implementations:
    
     export class ListitemService {…}
     
  • Create IListitem interface which is used in PnP storage:
    
     export interface IListItem {
        Id: number;
       Title: string;
       Author: { Title };
    }
    
  • Create the static storage items needed to implement caching:
    
     private static storageKey: string = 'listItemsKey';
        private static listItems: IListItem[] = [];
        private static storage = new PnPClientStorage();
    
    
  • Create the function which reads either from cache or from API depending on whether the data is available in the cache. The function below first checks the cache using the storage key. If it finds the data in the cache it returns it from cache else it calls the API and fetches the data, returns it to the caller as well as adds it to the cache.
    
     public static getListItems(context:any): Promise<IListItem[]> {
            return new Promise<IListItem[]>(async (resolve: (newListItems: IListItem[]) => void, reject: (error: any) => void) => {
               const loadedData = this.storage.session.get(this.storageKey);
               let items: IListItem[] = null;
               if ((window as any).loadingData) {
                   window.setTimeout((): void => {
                        this.getListItems(context).then((newListItems: IListItem[]): void => {
                           resolve(newListItems);
                        });
                    }, 50);
               }
               else {
                   if (!loadedData) {
                       (window as any).loadingData = true;
                        pnp.setup({
                            spfxContext: context
                          });
                        items = await  pnp.sp.web.lists.getByTitle("ConfigStore").items.getAll();
                        this.storage.session.put(this.storageKey, items);
                       console.info("from SharePoint list");
                        (window as any).loadingData = false;
                   }
                   else {
                       console.info("from Session storage");
                       items = loadedData;
                   }
                   resolve(items);
               }
           });
       }
    

Sample Application:

Let’s consider a simple application to illustrate the idea.

Sharing Data Across SPFx Web Parts Using PnP Storage

The above sample page has four different web parts which take inputs from a common ConfigStore list. In this case, since the config list has the properties for all the web parts in question, only one API call for the web part will load the config data and it will be cached in the PnP client storage. Subsequently, the other web parts will consume the data through the function call mentioned above.

In this simple application initially, the page was loading in a slower fashion but after implementing the said mechanism, the performance was seen to have improved significantly, say about 40%.

Conclusion:

There are other mechanisms available for sharing the data across web parts on a page. PnP Storage poses an easy to use and efficient option. It is also possible to actually share various data across web parts selectively in a very general fashion and one just needs to improve the functionality of the demonstrated artifact. Go ahead, take your pick and connect back, should you need any further clarification.

Leave a Reply

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