I'm trying to figure out the best way to do services in a React SPFx application. I'm still new to react and every example I have seen returns some html and what I need is a file that handles complex logic and return objects that I can reuse in other SPFx solutions. For example this is what I'm doing now.

import { BaseWebPartContext } from "@microsoft/sp-webpart-base";
import {spfi, SPFI, SPFx} from "@pnp/sp";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";
import "@pnp/sp/fields";
import "@pnp/sp/files";
import "@pnp/sp/folders";
import "@pnp/sp/batching";
import "@pnp/sp/views";
import {
  } from '@microsoft/sp-property-pane'; 
import {IColumnObject} from "./IColumnObject"; 
import {IDataObjectParams} from "./IDataObjectParams"; 
import { ISelectedObject } from "./ISelectedObject";

let spContext:SPFI;
export function setSPContext(context:BaseWebPartContext){
    spContext = spfi().using(SPFx(context));

export function otherThingThatNeedsToBeCalled(){
    ....something here

As you can see I have a let variable out in the open and I'm not sure if this is the proper way to do it. Most of the examples have a class for their services but that seems to defeat the purpose of using functional components. I would like it if I could just call the function like I'm doing here and return objects as I need them. Any examples of how you are doing services with functional components would be appreciated.

1 Answer 1


I usually setup PnP context as below. In below code I am setting up SP and Graph both. Also siteUrl parameter is used here. Pass the siteUrl to get data from that particular site collection. if it is not passed or blank, it will connect to the same site collection where WebPart is added.

import { WebPartContext } from '@microsoft/sp-webpart-base';
import { objectDefinedNotNull, stringIsNullOrEmpty } from '@pnp/core/util';
import { graphfi, GraphFI, SPFx as graphSPFx } from '@pnp/graph';
import { LogLevel, PnPLogging } from '@pnp/logging';
import { spfi, SPFI, SPFx as spSPFX } from '@pnp/sp';
import '@pnp/sp/items';
import '@pnp/sp/lists';
import '@pnp/sp/webs';
import '@pnp/sp/profiles';
import '@pnp/sp/fields';
import '@pnp/sp/batching';
import "@pnp/graph/users";

export const getSP = (context: WebPartContext, siteUrl?: string): SPFI => {
    let _sp: SPFI = null;
    if (_sp === null && context !== null && objectDefinedNotNull(context.pageContext)) {
        _sp = (stringIsNullOrEmpty(siteUrl))
            ? spfi().using(spSPFX({ pageContext: context.pageContext })).using(PnPLogging(LogLevel.Warning))
            : spfi(siteUrl).using(spSPFX({ pageContext: context.pageContext })).using(PnPLogging(LogLevel.Warning))
    return _sp;

export const getGraph = (context: WebPartContext, siteUrl?: string): GraphFI => {
    let _graph: GraphFI = null;
    if (_graph === null && context !== null && objectDefinedNotNull(context.pageContext)) {
        _graph = (stringIsNullOrEmpty(siteUrl))
            ? graphfi().using(graphSPFx(context)).using(PnPLogging(LogLevel.Warning))
            : graphfi(siteUrl).using(graphSPFx(context)).using(PnPLogging(LogLevel.Warning))
    return _graph;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.