Setting Up PnPjs Context Accessors for SharePoint and Microsoft Graph in SPFx
This article provides a technical overview of how to create and manage context-aware singleton accessors for both SharePoint and Microsoft Graph using the PnPjs library in a SharePoint Framework (SPFx) project. The code pattern presented ensures efficient initialization and reuse of SPFI and GraphFI instances, which are critical for performing REST operations against SharePoint and Graph APIs.
Objective
To enable a clean, reusable, and maintainable method for instantiating PnPjs clients (spfi, graphfi) tied to the current SPFx WebPartContext, avoiding redundant initializations and ensuring optimal performance across components.
Technologies Used
- SPFx: Provides the
WebPartContextrequired to authenticate and authorize API calls. - PnPjs: A fluent JavaScript API for SharePoint and Graph, simplifying REST operations.
- TypeScript: Enables strong typing and development-time tooling.
Core Concepts and Implementation
1. Importing Required Modules
The code starts by importing essential packages from @pnp/sp and @pnp/graph and includes side-effect imports to extend the functionality of the PnPjs core.
import { spfi, SPFI, SPFx as spSPFx } from "@pnp/sp";
import { graphfi, GraphFI, SPFx as graphSPFx } from "@pnp/graph";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";
import "@pnp/sp/batching";
These side-effect imports (like @pnp/sp/items) are necessary to enable chained calls like .web.lists.getByTitle().items.add().
2. Singleton Pattern for SP and Graph Clients
The use of var and simple checks (if (_sp === undefined || _sp === null)) ensures that these objects are only created once during the application lifecycle.
var _sp: SPFI;
var _graph: GraphFI;
This pattern is crucial for performance and memory efficiency in SPFx solutions where multiple components may need to access the same context.
3. getSP Function
This function returns an instance of the SharePoint Fluent Interface (SPFI) configured for the current SPFx context.
export const getSP = (context?: WebPartContext): SPFI => {
if (_sp === undefined || _sp === null) {
_sp = spfi().using(spSPFx(context as ISPFXContext));
}
return _sp;
};
spfi()creates the base instance..using(spSPFx(...))applies the context, which enables token-based authorization using the current user’s credentials.
4. getGraph Function
Similarly, getGraph initializes and returns a context-bound Microsoft Graph client (GraphFI):
export const getGraph = (context?: WebPartContext): GraphFI => {
if (_graph === undefined || _graph === null) {
_graph = graphfi().using(graphSPFx(context as ISPFXContext));
}
return _graph;
};
This allows access to resources such as user profiles, Teams, Planner, etc., via Microsoft Graph API endpoints.
5. Logging Note
Although the comments mention the need for @pnp/logging, it is not explicitly used in the code snippet. If extended, this would allow debugging output based on different log levels, which is often essential during development.
Integration Reference
For full context and usage examples, refer to the official PnPjs documentation:
Getting Started with PnPjs: https://pnp.github.io/pnpjs/getting-started/
Summary Table
| Aspect | Details |
|---|---|
| Purpose | Context-aware singleton for SharePoint and Graph clients |
| Key Libraries | @pnp/sp, @pnp/graph, @microsoft/sp-webpart-base |
| Output Objects | SPFI, GraphFI |
| Authentication Method | Via SPFx(context) helper |
| Usage Pattern | Singleton with lazy instantiation |
| Optimization Benefit | Prevents reinitialization and ensures token reuse |
| Dependency Imports | Lists, items, webs, batching |
| Documentation Reference | PnPjs Getting Started |
By adopting this pattern, SPFx developers can centralize context configuration, improve code readability, and build scalable web parts or extensions that interact efficiently with SharePoint and Microsoft 365 services.
