PnP React Hooks

PnP React Hooks is a wrapper library for PnPjs, provides configurable React hooks for SharePoint API to speed up development for simple SPFx webparts and components.

Example usage:

import * as React from "react";
import { useListItems, useCurrentUser } from "pnp-react-hooks";

export const ExampleComponent = () => {
	const currentUser = useCurrentUser();

	const items = useListItems("My List", {
		query: {
			select: ["Title", "Id", "Author/Title"],
			expand: ["Author"],
			filter: `Author eq ${currentUser?.Id}`
		},
		disabled: !currentUser
	});

	return (<ul>
		{items?.map(item => (<li key={item.Id}>{item.Title}</li>))}
	</ul>);
};

Installation

npm install pnp-react-hooks @pnp/sp react

@pnp/sp and react packages are peer dependencies.

Peer dependencySupported versions
@pnp/sp4.1.0 or later
react16.9.* to 18.*.*

Features

  • Build simple web parts quickly with less code.
  • TypeScript support.
  • Automatically tracks parameter changes and refreshes data as needed.
  • Easy to tree-shake unused code with modern JS bundlers.
  • Can be configured for multiple sites with an option provider.
  • Supports PnPjs behaviors.

Questions and Suggestions

If you find any issue or have a suggestion on how project can be improved feel free to create an issue on Github.

Getting Started

SPFx

  1. Install pnp-react-hooks and @pnp/sp packages to your SPFx webpart project.
npm install pnp-react-hooks @pnp/sp
  1. Update module imports, onInit() and render() functions on <YourWebpartName>.tsx file.

PnpReactHookExamplesWebPart.ts

// <Other Webpart imports>
// Import pnp-react-hooks helper function and option type
import { PnpHookGlobalOptions, createProviderElement } from 'pnp-react-hooks';
// import PnPjs
import { spfi, SPFx} from '@pnp/sp';

export default class PnpReactHookExamplesWebPart extends BaseClientSideWebPart<IPnpReactHookExamplesWebPartProps>
{
  private _isDarkTheme: boolean = false;
  private _environmentMessage: string = '';
  private _theme: IReadonlyTheme;
  private _hookOptions: PnpHookGlobalOptions;

  // Create onInit function to initialize options.
  protected onInit(): Promise<void>
  {
    return this._getEnvironmentMessage().then(message =>
    {
      this._environmentMessage = message;
      // Initialize PnPjs sp context.
      const sp = spfi().using(SPFx(this.context));

      // Setup your default PnP React hooks options.
      this._hookOptions = {
        sp: sp,
        disabled: "auto"
      };
    });
  }

  public render(): void
  {
    const element: React.ReactElement<IPnpReactHookExamplesProps> = React.createElement(
      PnpReactHookExamples,
      {
        description: this.properties.description,
      }
    );

    // Use helper function to create React elements.
    const rootElement = createProviderElement(this._hookOptions, element);

    // Render root element.
    ReactDom.render(rootElement, this.domElement);
  }

}
  1. Start using hooks in your webpart components.

PnpReactHookExamples.tsx

import * as React from 'react';
import { IPnpReactHookExamplesProps } from './IPnpReactHookExamplesProps';
import { useCurrentUser } from "pnp-react-hooks";

const PnpReactHookExamples = (props: IPnpReactHookExamplesProps) => {
  const me = useCurrentUser({
    query: {
    select: ["Title"]
  }
});

return (<div>{me?.Title}</div>);
};

export default PnpReactHookExamples;

Common Hook Options

All hook options have the following common properties:

disabled: Disables hook execution if supplied value or predicate function result is true. It also supports "auto" which handles the common cases like null list name, undefined user name etc.

query: OData query parameters supported by resource type. Automatically tracked for changes with deep comparison.

For example, the following query1 and query2 are considered as equal and they won't cause any re-render.

const query1 = {
    select: ["Title", "Id", "Lookup/Id"],
    expand: ["Lookup"]
}

const query2 = {
    expand: ["Lookup"]
    select: ["Id", "Lookup/Id", "Title"],
}

keepPreviousState: When enabled, hook does not reset it's current state to undefined before sending a new request.

sp: Overrides PnpJs SPFI instance. Default uses context-provided instance.

behaviors: Sets PnpJs pipeline behaviors to each request.

error: Error handling mode or custom error callback. Use ErrorMode.Default (0) for throwing error, ErrorMode.Suppress (1) for ignoring the errors.

type PnpHookOptions = {
    disabled?: "auto" | boolean | (...args[]) => boolean;
    query?: {
        expand?: string[];
        select?: string[];
        // Extra properties are available for collection types.
        top?: number;
        orderBy?: string;
        orderyByAscending?: boolean;
        skip?: number;
        filter?: string;
    },
    keepPreviousState?: boolean;
    sp?: SPFI;
    behaviors?: TimelinePipe<any>[];
    error?: 0 | 1 | (err:Error) => void;
}

Option Provider

All hooks can be configured with PnpHookOptionProvider component. SP Hooks use options from the nearest parent provider similar to how React contexts works.

import * as React from "react";
import { useWebInfo, PnpHookOptionProvider, PnpHookGlobalOptions } from "pnp-react-hooks";
import { Caching } from "@pnp/queryable";
import { spfi, SPBrowser } from "@pnp/sp";

/** @type{PnpHookGlobalOptions} **/
const options = {
    disabled: "auto",
    keepPreviousState: true,
    error: console.debug,
    sp: spfi().using(SPBrowser())
};

/** @type{PnpHookGlobalOptions} **/
const cachedOptions = {
    disabled: "auto",
    keepPreviousState: true,
    error: console.debug,
    sp: spfi().using(SPBrowser(), Caching())
};

export function Main() {
    return(
        <>
            <PnpHookOptionProvider value={options}>
                <CurrentWebInfo />
                <UserInfo />
            </PnpHookOptionProvider>
            <PnpHookOptionProvider value={cachedOptions}>
                <CurrentWebInfo />
                <UserInfo />
            </PnpHookOptionProvider>
        </>
    );
}

export function CurrentWebInfo() {
    const web = useWebInfo();
    return <h1>{web?.Title}</h1>;
}

export function UserInfo() {
    const user = useCurrentUser();
    return <h2>{user?.Title}</h2>;
}

For non-Jsx initializers, PnpHookOptionProvider can be created with createProviderElement function.

createProviderElement(options: PnpHOokGlobalOptions, ...children: any[]);
import * as React from "react";
import * as ReactDom from "react-dom";
import { spfi, SPBrowser } from "@pnp/sp";
import { createProviderElement, PnpHookGlobalOptions } from 'pnp-react-hooks';

// create options
const options: PnpHookGlobalOptions = {
    sp: spfi("<sharepoint-site-url>").using(SPBrowser()),
    disabled: "auto",
    error: (err) => console.debug(err)
};

// Create your child elements
const childElement0 = React.createElement(PnpReactHookExamples, { description: "Child 0" });
const childElement1 = React.createElement(PnpReactHookExamples, { description: "Child 1" });

// Create root element with provider
const rootElement = createProviderElement(options, childElement0, childElement1);

ReactDom.render(rootElement, this.domElement);

Created React DOM tree is:

<PnpHookOptionProvider value={options}>
    <PnpReactHookExamples description="Child 0" />
    <PnpReactHookExamples description="Child 1" />
</PnpHookOptionProvider>

Accessing Options

usePnpHookOptions(): PnpHookGlobalOptions;

Returns options from the nearest PnpHookOptionProvider.

Example

import { usePnpHookOptions } from "pnp-react-hooks";

function ExampleComponent() {
    const options = usePnpHookOptions();

    .....
    .....
    .....
    .....
}

Sp Hooks

useApp

useApp<T>(appId: string, options?:WebAppOptions, deps?: any[]) : T | null | undefined;

Returns an app details for the given Id.

Examples

Get app from site collections app catalog,

const app = useApp("5ee53613-bc0f-4b2a-9904-b21afd8431a7");

Query app propeties,

const appWithQuery = useApp("5ee53613-bc0f-4b2a-9904-b21afd8431a7", {
  query: {
    select: ["Title", "Id", "IsEnabled"]
  }
});

Get app from tenant app catalog,

const tenantApp = useApp("5ee53613-bc0f-4b2a-9904-b21afd8431a7", {
  scope: "tenant"
});

Set scope to site collection explicitly, same as setting scope to undefined,

const tenantApp = useApp("5ee53613-bc0f-4b2a-9904-b21afd8431a7", {
  scope: "sitecollection"
});

Parameters

NameTypeDescriptionTracked for changes
appIdstringApp UUID string.Yes
options?WebAppOptionsuseApp hook optionsPartially
deps?DependencyListHook dependency list.Yes

useApps

useApps<T>(options?: WebAppsOptions, deps?: any[]): T[] | null | undefined;

Returns app collection from app catalog.

Examples

Get apps from site collections app catalog,

const apps = useApps();

Get apps from tenants app catalog,

const apps = useApps({
  scope: "tenant"
});

Set scope to site collection explicitly,

const apps = useApps({
  scope: "sitecollection"
});

Query apps from app catalog,

const filteredApps = useApps({ 
  query: { 
    select: ["Title", "Id", "IsEnabled"],
    filter: "IsEnabled eq true" 
  }
});

Parameters

NameTypeDescriptionTracked for changes
options?WebAppsOptionsuseApps hook optionsPartially
deps?DependencyListHook dependency list.Yes

useAttachment

useAttachment(
	attachmentName:string,
	itemId:number,
	list:string,
	options?: AttachmentInfoOptions,
	deps?:any[]): IAttachmentInfo | null | undefined;

useAttachment(
	attachmentName:string,
	itemId:number,
	list:string,
	options?: AttachmentTextOptions,
	deps?:any[]): string | null | undefined;

useAttachment(
	attachmentName:string,
	itemId:number,
	list:string,
	options?: AttachmentBlobOptions,
	deps?:any[]): Blob | null | undefined;

useAttachment(
	attachmentName:string,
	itemId:number,
	list:string,
	options?: AttachmentBufferOptions,
	deps?:any[]): ArrayBuffer | null | undefined;

Returns an attachment info or attachment content from item.

Examples

Get attachment info,

const attachmentProps = useAttachment("my-attachment.txt", 12, "My List");

Query attachment info properties,

const attachmentProps = useAttachment("my-attachment.txt", 12, "My List"), {
	query: {
		select: ["Title", "Id"]
	}
});

Get attachment content as Blob,

const contentAsBlob = useAttachment("my-attachment.txt", 12, "My List", {
	type: "blob"
});

Get attachment content as ArrayBuffer,

const contentAsBuffer = useAttachment("my-attachment.txt", 12, "My List", {
	type: "buffer"
});

Get attachment content as string,

const contentAsText = useAttachment("my-attachment.txt", 12, "My List", {
	type: "text"
});

Parameters

NameTypeDescriptionTracked for changes
attachmentNamestringAttachment nameYes
itemIdnumberList item IDYes
liststringTarget list UUID or titleYes
options?AttachmentInfoOptions | AttachmentBlobOptions | AttachmentTextOptions | AttachmentBufferOptionsuseAttachment hook optionsPartially
deps?DependencyListHook dependency list.Yes

useAttachments

useAttachments(
	itemId: number,
	list: string,
	options?: ItemAttachmentsOptions,
	deps: any[]): IAttachmentInfo[] | null | undefined;

Returns all attachments from an item.

Examples

Get all attachments from an item,

const attachments = useAttachments(10, "My List");

Query list items attachments,

const filteredAttachments = useAttachments(10, "5ee53613-bc0f-4b2a-9904-b21afd8431a7", {
	query: {
		select: ["Name", "Id"],
		filter: "substringof('.pdf', Name) eq true"
	}
});

Parameters

NameTypeDescriptionTracked for changes
itemIdnumberList item IDYes
liststringTarget list UUID or titleYes
options?ItemAttachmentsOptionsuseAttachments hook optionsPartially
deps?DependencyListHook dependency list.Yes

useChanges

useChanges<T>(
    changeQuery: IChangeQuery,
    options?: ChangesOptions,
    deps?: any[]): T[] | null | undefined;

Returns web or list change collection. Use ChangesOptions.list property to get list changes instead of web changes.

Examples

Get web changes,

const changeQuery = {
    Add:true,
    Alert:true,
    ChangeTokenEnd: { StringValue: "some end token string" },
    ChangeTokenStart: { StringValue: "some start token string" }
};

const webChanges = useChanges(myQuery, undefined, [
    myQuery?.ChangeTokenStart?.StringValue,
    myQuery?.ChangeTokenEnd?.StringValue
]);

Get list changes by using list title and UUID,

const listChangeQuery = {
    Add:true,
    Update:true,
    Delete:true,
    ChangeTokenEnd: { StringValue: "some end token string" },
    ChangeTokenStart: { StringValue: "some start token string" }
};

// getting list changes by list title
const listChanges = useChanges(
	listChangeQuery,
	{ list: "My List Title" },
	[
		myQuery?.ChangeTokenStart?.StringValue,
		myQuery?.ChangeTokenEnd?.StringValue
	]
);

// getting list changes by list Id
const anotherListChanges = useChanges(
	listChangeQuery,
	{ list: "61ca5ff8-f553-4d51-a761-89225b069a4f" }, 
	[
	    myQuery?.ChangeTokenStart?.StringValue,
	    myQuery?.ChangeTokenEnd?.StringValue
	]
);

Parameters

NameTypeDescriptionTracked for changes
changeQueryIChangeQueryChange query objectNo
options?ChangesOptionsuseChanges hook optionsPartially
deps?DependencyListHook dependency listYes

useContentTypes

useContentTypes(
  options?: ContentTypeOptions,
  deps?: any[]): IContentTypeInfo[] | null | undefined;

Returns content types of web or list. Use ContentTypeOptions.list property to get list content types instead of web content types.

Examples

Get web content types,

const webContentTypes = useContentTypes();

Get list content types by list Id,

const listContentTypes = useContentTypes({
  list: "5ee53613-bc0f-4b2a-9904-b21afd8431a7"
});

Get list content types by list title,

const listContentTypes = useContentTypes({
  list: "My List Title"
});

Parameters

NameTypeDescriptionTracked for changes
options?ContentTypeOptionsuseContentTypes hook options.Partially
deps?DependencyListHook dependency listYes

useCurrentUser

useCurrentUser(
  options?: CurrentUserInfoOptions, 
  deps?: any[]): ISiteUserInfo | null | undefined;

Returns current user information.

Examples

Get basic user properties,

const userAllProps = useCurrentUser();

Get user properties with query,

const user = useCurrentUser({
  query: {
    select: ["Title", "Id", "LoginName"]
  }
});

Parameters

NameTypeDescriptionTracked for changes
options?CurrentUserInfoOptionsuseCurrentUser hook options.Partially
deps?DependencyListHook dependency listYes

useFeatures

useFeatures(
	options?: FeaturesOptions,
	deps?: any[]): IFeatureInfo[] | null | undefined;

Returns site or web feature collection. Scope type can be defined in FeaturesOptions.scope property.

Examples

Get web features,

const webFeatures = useFeatures();

Get site features,

const siteFeatures = useFeatures({
	scope: "site"
});

Parameters

NameTypeDescriptionTracked for changes
options?FeaturesOptionsuseFeature hook optionsPartially
deps?DependencyListHook dependency list.Yes

useField

useField(
   fieldId: string, 
   options?: FieldOptions, 
   deps? any[]): IFieldInfo | null | undefined;

Returns a field from web or list.

Examples

Get web field info,

const webFields = useField("5ee53613-bc0f-4b2a-9904-b21afd8431a7");

Get list field info,

const listFields = useField("MyCustomFieldInternalName", {
   list: "5ee53613-bc0f-4b2a-9904-b21afd8431a7"
});

Parameters

NameTypeDescriptionTracked for changes
fieldIdstringField internal name or IdYes
options?FieldOptionsuseField hook optionsPartially
deps?DependencyListHook dependency list.Yes

useFields

useFields(
	options?: FieldsOptions, 
	deps?: any[]): IFieldInfo[] | null | undefined;

Returns field collection from web or list. Use FieldsOptions.list property to set target list.

Examples

Get web fields,

const webFields = useFields();

Get list fields,

const listFields = useFields({
	list: "5ee53613-bc0f-4b2a-9904-b21afd8431a7"
});

Query fields,

const listFields = useFields({
	list: "My List Title",
	query:{
		select: ["InternalName", "Title", "Id"]
	}
});

Parameters

NameTypeDescriptionTracked for changes
options?FieldsOptionsuseFields hook optionsPartially
deps?DependencyListHook dependency list.Yes

useFile

useFile(
	fileId: string,
	options?: FileInfoOptions,
	deps?: any[]): IFileInfo | null | undefined;

useFile(
	fileId: string,
	options?: FileBlobOptions,
	deps?: any[]): Blob | null | undefined;

useFile(
	fileId: string,
	options?: FileTextOptions,
	deps?: any[]): string | null | undefined;

useFile(
	fileId: string,
	options?: FileBufferOptions,
	deps?: any[]): ArrayBuffer | null | undefined;

Returns a file from file collection.

Examples

Get file info by ID,

const fileInfo = useFile("5ee53613-bc0f-4b2a-9904-b21afd8431a7");

Get file info by server relative path,

const assetInfo = useFile("/sites/mysite/SiteAssets/example.png");

Get file content as Blob,

const fileContentAsBlob = useFile("5ee53613-bc0f-4b2a-9904-b21afd8431a7", {
	type: "blob"
});

Get file content as ArrayBuffer,

const fileContentAsBuffer = useFile("5ee53613-bc0f-4b2a-9904-b21afd8431a7", {
	type: "buffer"
});

Get file content as string,

const fileContentAsText = useFile("5ee53613-bc0f-4b2a-9904-b21afd8431a7", {
	type: "text"
});

Parameters

NameTypeDescriptionTracked for changes
fileIdstringfile UUID or server relative pathYes
options?FileInfoOptions | FileBlobOptions | FileTextOptions | FileBufferOptionsuseFile hook optionsPartially
deps?DependencyListHook dependency list.Yes

useFiles

useFiles(
	folderId: string,
	options?: FilesOptions,
	deps?: any[]): IFileInfo[] | null | undefined;

Returns file collection from folder.

Examples

Get all files from a folder by UUID,

const files = useFiles("5ee53613-bc0f-4b2a-9904-b21afd8431a7");

Get all files from a folder by server relative URL,

const siteAssetsFiles = useFiles("/sites/mysite/SiteAssets", {
	query: {
		select: ["Id", "Name", "ServerRelativeUrl", "Author/Title"]
		expand: ["Author"]
	}
});

Parameters

NameTypeDescriptionTracked for changes
folderIdstringFolder UUID or server relative URLYes
options?FilesOptionsuseFiles hook optionsPartially
deps?DependencyListHook dependency list.Yes

useFolder

useFolder(
	folderId: string,
	options?: FolderOptions,
	deps?: any[]): IFolderInfo | null | undefined;

Return a folder.

Examples

Get folder by Id,

const folder = useFolder("5ee53613-bc0f-4b2a-9904-b21afd8431a7");

Get folder by server relative url,

const siteAssets = useFolder("/sites/mysite/SiteAssets", {
	query: {
		select: ["Id", "Name", "ServerRelativeUrl"]
	}
});

Parameters

NameTypeDescriptionTracked for changes
folderIdstringFolder UUID or server relative pathYes
options?FolderOptionsuseFolder hook optionsPartially
deps?DependencyListHook dependency list.Yes

useFolders

useFolders(
	options?: FoldersOptions, 
	deps?: any[]): IFolderInfo[] | null | undefined;

Returns folders from root. Use FoldersOptions.rootFolderId property to change root folder.

Examples

Get folders from webs root,

const rootFolders = useFolders();

Get folders from different folder,

const folders = useFolders({
	rootFolderId: "5ee53613-bc0f-4b2a-9904-b21afd8431a7"
});

const folders = useFolders({
	rootFolderId: "/sites/mysite/SiteAssets"
});

Query folders,

const filteredFolders = useFolders({
	query:{
		select: ["Id", "Title"],
		filter: "substringof('SiteAssets', Title) eq true"
	}
});

Parameters

NameTypeDescriptionTracked for changes
options?FoldersOptionsuseFolders hook optionsPartially
deps?DependencyListHook dependency list.Yes

useGroup

useGroup(
	groupId: string | number,
	options?: GroupOptions,
	deps?: any[]): ISiteGroupInfo | null | undefined;

Returns a group from group collection.

Examples

Get group info by Id,

const group = useGroup(10);

Get group info by name

const mySpGroup = useGroup("My SharePoint Group");

Query group properties,

const mySpGroup = useGroup("My SharePoint Group", {
	query: {
		select: ["Title", "Id"]
	}
});

Parameters

NameTypeDescriptionTracked for changes
groupIdstring | numberGroup Id or nameYes
options?GroupOptionsuseApps hook optionsPartially
deps?DependencyListHook dependency list.Yes

useGroups

useGroups(options?: GroupsOptions, deps?: any[]): ISiteGroupInfo[] | null | undefined;

Returns group collection. Use GroupsOptions.userId property to get groups for specific user.

Examples

Get all groups,

const groups = useGroups();

Get groups for a specific user,

const userGroups = useGroups({
	userId: 20
});

const userGroupsByEmail = useGroups({
	userId: "user@example.onmicrosoft.com"
});

const userGroupsByLoginName = useGroups({
	userId: "i:0#.f|membership|user@example.onmicrosoft.com"
});

Parameters

NameTypeDescriptionTracked for changes
options?GroupsOptionsuseGroups hook optionsPartially
deps?DependencyListHook dependency list.Yes

useGroupUser

useGroupUser(
  groupId: string | number,
  userId: string | number,
  options?: GroupUserOptions,
  deps?: any[]): ISiteUserInfo | null | undefined;

Returns an user from specific group user collection.

Examples

const groupUser = useGroupUser(10, 27);

const groupUser = useGroupUser("My SharePoint Group", 27);

const groupUser = useGroupUser("My SharePoint Group", "user@example.onmicrosoft.com");

const groupUser = useGroupUser("My SharePoint Group", "i:0#.f|membership|user@example.onmicrosoft.com");

Parameters

NameTypeDescriptionTracked for changes
groupIdstring | numberGroup name or IdYes
userIdstring | numberUser email, login name or IdYes
options?WebAppsOptionsuseApps hook optionsPartially
deps?DependencyListHook dependency list.Yes

useGroupUsers

useGroupUsers(
	groupId: `string` | `number`,
	options?: GroupUsersOptions,
	deps?: any[]): ISiteUserInfo[] | null | undefined;

Returns user collection from specific group.

Examples

Get group users,

const myGroupUsers = useGroupUsers(10);

const myGroupUsers = useGroupUsers("My SharePoint Group");

Query group users,

const filteredGroupUsers = useGroupUsers("My SharePoint Group", {
	query:{
		select: ["LoginName", "Title"],
		filter: "IsSiteAdmin eq false"
	}
});

Parameters

NameTypeDescriptionTracked for changes
groupIdstring | numberGroup Id or nameYes
options?GroupUsersOptionsuseGroupUsers hook optionsPartially
deps?DependencyListHook dependency list.Yes

useHasPermission

useHasPermission(
	permissionKinds: PermissionKind | PermissionKind[],
	options?: UserPermissionOptions,
	deps?): boolean | null | undefined;

Returns true if user has permission on scope. If not returns false. Use UserPermissionOptions.userId for another user and UserPermissionOptions.scope for permission scope. Default is current user permission on current web scope.

Examples

Check current users web permissions,

import { PermissionKind } from "@pnp/sp/security";
import { useHasPermission } from "pnp-react-hooks";

const permissions = PermissionKind.ViewListItems | PermissionKind.ViewPages
const hasPermission = useHasPermission(permissions);

Check another users permission on web,

import { PermissionKind } from "@pnp/sp/security";
import { useHasPermission } from "pnp-react-hooks";

const permissions = PermissionKind.ViewListItems | PermissionKind.ViewPages
const userHasPermission = useHasPermission(permissions, {
	userId: "user@example.onmicrosoft.com"
});

Check list permissions,

import { PermissionKind } from "@pnp/sp/security";
import { useHasPermission } from "pnp-react-hooks";

const permissions = PermissionKind.ViewListItems | PermissionKind.ViewPages
const hasPermission = useHasPermission(permissions, {
	scope: {
		list: "My List Title"
	}
});

Check item permissions,

import { PermissionKind } from "@pnp/sp/security";
import { useHasPermission } from "pnp-react-hooks";

const permissions = PermissionKind.ViewListItems | PermissionKind.ViewPages
const hasPermission = useHasPermission(permissions, {
	scope: {
		list: "My List Title",
		item: 12
	}
});

Parameters

NameTypeDescriptionTracked for changes
permissionKindsPermissionKind | PermissionKind[]SP permission kind array or valueYes
options?UserPermissionOptionsuseHasPermission hook optionsPartially
deps?DependencyListHook dependency list.Yes

useIsMemberOf

useIsMemberOf(
	groupId: string | number,
	options?: IsMemberOfOptions,
	deps?: any[]): [boolean, ISiteGroupInfo];

Returns users membership info for the specified group. Use IsMemberOfOptions.userId property to check another user. Default is current user.

Examples

Get current users membership info,

const [isMember, groupInfo] = useIsMemberOf(10);

Get different users membership info,

const [isMember, groupInfo] = useIsMemberOf("My SharePoint Group", {
	userId: "user@example.onmicrosoft.com"
});

const [isMember, groupInfo] = useIsMemberOf("My SharePoint Group", {
	userId: 25
});

const [isMember, groupInfo] = useIsMemberOf(10, {
	userId: "i:0#.f|membership|user@example.onmicrosoft.com"
});

Parameters

NameTypeDescriptionTracked for changes
groupIdstringGroup name or IdYes
options?IsMemberOfOptionsuseIsMemberOf hook optionsPartially
deps?DependencyListHook dependency list.Yes

useItemComments

useItemComments(
  itemId: number,
  list: string,
  options?: ItemCommentsOptions,
  deps?: any[]): ICommentInfo[] | null | undefined;

Returns comments for specific list item.

Examples

Get list items comments,

const comments = useItemComments(12, "My List Title");
const comments = useItemComments(12, "5ee53613-bc0f-4b2a-9904-b21afd8431a7");

Parameters

NameTypeDescriptionTracked for changes
itemIdnumberItem IdYes
liststringList UUID or titleYes
options?ItemCommentsOptionsuseItemComments hook optionsPartially
deps?DependencyListHook dependency list.Yes

useListAsStream

useListAsStream(
	list: string,
	parameters: RenderListParameters,
	options?: ListAsStreamOptions,
	deps?: any[]): IRenderListDataAsStreamResult | null | undefined;

Returns data for the specified query view.

Examples

Basic usage

const renderData = useListAsStream("5ee53613-bc0f-4b2a-9904-b21afd8431a7", {
	dataParameters: {
			Paging: "TRUE",
			RenderOptions: RenderListDataOptions.ListData
		},
		dataOverrideParameters: {
			PageFirstRow: "1",
			PageLastRow: "30",
		},
		useQueryParameters: true
	}
);

Parameters

NameTypeDescriptionTracked for changes
liststringList UUID or titleYes
parametersRenderListParametersRender parametersNo
options?ListAsStreamOptionsuseListAsStream hook optionsPartially
deps?DependencyListHook dependency list.Yes

useListChangeToken

useListChangeToken(
        list: string,
        options?: ListTokenOptions,
        deps?: any[]): IChangeTokenInfo | null | undefined;

Returns lists current change token and last modified dates.

Examples

Get list change tokens,

const changeDetails = useListChangeToken("5ee53613-bc0f-4b2a-9904-b21afd8431a7");

const changeDetails = useListChangeToken("My List Title");

Parameters

NameTypeDescriptionTracked for changes
liststringList UUID or titleYes
options?ListTokenOptionsuseListChangeToken hook optionsPartially
deps?DependencyListHook dependency list.Yes

Remarks

You can also use useList to get exact same change info.

const listInfo = useList("5ee53613-bc0f-4b2a-9904-b21afd8431a7", {
    query: {
        select: [
             "CurrentChangeToken",
             "LastItemDeletedDate",
             "LastItemModifiedDate",
             "LastItemUserModifiedDate" ]
    }
});

useListItem

useListItem<T>(
	itemId: number,
	list: string,
	options?: listItemOptions,
	deps?: any[]): T | null | undefined;

Returns an item from specified list.

Examples

Get a list item,

const item = useListItem(10, "5ee53613-bc0f-4b2a-9904-b21afd8431a7");

Get a list item with query and custom type,

export interface MyItem {
	Id: number;
	Title: string;
	Created: string;
	Modified: string;
	Author : {
		Title: string;
	}
}

const myItem = useListItem<MyItem>(10, "My List Title", {
	query: {
		select: ["Title", "Id", "Author/Title", "Created", "Modified"],
		expand: ["Author"]
	}
});

Parameters

NameTypeDescriptionTracked for changes
itemIdnumberItem IdYes
liststringList UUID or titleYes
options?ListItemOptionsuseListItem hook optionsPartially
deps?DependencyListHook dependency list.Yes

useListItems

useListItems<T>(
	list: string,
	options?: ListItemsOptions,
	deps?: any[]): T[] | null | undefined;

useListItems<T>(
	list: string,
	options?: PagedItemsOptions,
	deps?: any[]): [T[] | null | undefined, nextPageDispatch, boolean];

useListItems<T>(
	list: string,
	options?: AllItemsOptions,
	deps?: any[]): T[] | null | undefined;

Examples

Get list items,

const items = useListItems("My List Title");

Query list items,

const myItems = useListItems<MyItem>("5ee53613-bc0f-4b2a-9904-b21afd8431a7", {
	query: {
		select: ["Title", "Id", "Author/Title", "Created", "Modified"],
		expand: ["Author"]
	},
	mode: ListItemsMode.Default // 0
});

Get list items with custom paging,

const [page, nextPage, done] = useListItems("My List Title", {
	mode: ListItemsMode.Paged
});

// You can get next page with nextPageDispatch function.
if(!done) {
	nextPage();

	// Optionally pass a callback function.
	nextPage((data) => console.debug(data));
}

Get all items without 5000 item limit (Not recommended for most cases),

const items = useListItems("My List Title", {
	mode: ListItemsMode.All // 1
});

Parameters

NameTypeDescriptionTracked for changes
liststringList UUID or TitleYes
options?ListItemsOptions | PagedListItems | AllListItemsuseListItems hook optionsPartially
deps?DependencyListHook dependency list.Yes

useList

useList(
	list: string,
	options?: ListOptions,
	deps?: any[]): IListInfo | null | undefined;

Return a list from list collection.

Examples

Get list info,

const listInfo = useList("5ee53613-bc0f-4b2a-9904-b21afd8431a7");

Query list properties,

const myList = useList("My List Title", {
	query: {
		select: ["Title", "Id"],
		filter: "ItemCount eq 0"
	}
});

Parameters

NameTypeDescriptionTracked for changes
liststringList UUID or titleYes
options?ListOptionsuseList hook optionsPartially
deps?DependencyListHook dependency list.Yes

useLists

useLists(options?: ListsOptions, deps?: any[]): IListInfo[] | null | undefined;

Returns list collection.

Examples

Get site lists,

const listInfo = useLists();

Query site lists,

const emptyLists = useList({
	query: {
		select: ["Title", "Id"],
		filter: "ItemCount eq 0"
	}
});

Parameters

NameTypeDescriptionTracked for changes
options?ListsOptionsuseLists hook optionsPartially
deps?DependencyListHook dependency list.Yes

useNavigation

useNavigation(
	options?: NavigationOptions,
	deps?: any[]): INavNodeInfo[] | null | undefined;

Returns web navigation nodes. Use NavigationOptions.type property to change navigation type. Default is topNavigation.

Examples

Get top navigation nodes,

const topNav = useNavigation();

// Explicit type
const topNav = useNavigation({
	type: "topNavigation"
});

Get quick launch navigation nodes,

const quickLaunch = useNavigation({
	type: "quickLaunch"
});

Parameters

NameTypeDescriptionTracked for changes
options?NavigationOptionsuseNavigation hook optionsPartially
deps?DependencyListHook dependency list.Yes

usePageComments

usePageComments(
  pageRelativePath: string,
  options?: PageCommentsOptions,
  deps?: any[]): ICommentInfo[] | undefined | null;

Returns comment collection from page.

Examples

Get page comments,

const pageComments = usePageComments("/sites/mysite/Pages/Home.aspx");

Parameters

NameTypeDescriptionTracked for changes
pageRelativePathstringPage server relative pathYes
options?PageCommentsOptionsuseApps hook optionsPartially
deps?DependencyListHook dependency list.Yes

useProfiles

useProfile<T>(
  loginName: string,
  options?: ProfileOptions,
  deps?: any[]): T | null | undefined;

Returns an user profile for specified login name or email.

Examples

Get profile by user email,

const profileByEmail = useProfile("user@example.onmicrosoft.com");

Get profile by user login name,

const profile = useProfile("i:0#.f|membership|user@example.onmicrosoft.com");

Parameters

NameTypeDescriptionTracked for changes
loginNamestringUser login name or emailYes
options?ProfileOptionsuseProfile hook optionsPartially
deps?DependencyListHook dependency list.Yes

useRecycleBinItem

useRecycleBinItem(
    itemId: string,
    options?:RecycleBinItemOptions,
    deps?: any[]): IRecycleBinItemObject` | null | undefined;

Returns an item from recycle bin.

Examples

Web recycle bin item

Get item from webs recycle bin,

const item = useRecycleBinItem("3e33c760-dfd2-4107-ac4a-838b169ea3d8");

// Explicit scope type
const item = useRecycleBinItem("3e33c760-dfd2-4107-ac4a-838b169ea3d8", {
    scope: "web"
});

Get item from site collections recycle bin,

const item = useRecycleBinItem("3e33c760-dfd2-4107-ac4a-838b169ea3d8", {
    scope: "site"
});

Query recycle bin items properties,

const item = useRecycleBinItem("3e33c760-dfd2-4107-ac4a-838b169ea3d8", {
    query: {
        select: ["Title", "ItemState"],
    }
});

Parameters

NameTypeDescriptionTracked for changes
itemIdstringItem UUIDYes
options?WebAppsOptionsuseRecycleBinItem hook optionsPartially
deps?DependencyListHook dependency list.Yes

useRecycleBinItems

useRecycleBinItems(
    options?: RecycleBinItemsOptions,
    deps?: any[]): IRecycleBinItemObject[] | null | undefined;

Returns all recycle bin items.

Examples

Get web recycle bin items,

const items = useRecycleBinItems();

// Explicit scope
const items = useRecycleBinItems({
    scope: "web"
});

Get site recycle bin items,

const items = useRecycleBinItems({
    scope: "site"
});

Query recycle bin items,

const items = useRecycleBinItems({
    query: {
        top: 2,
        select: ["Title", "ItemState"],
    }
});

Parameters

NameTypeDescriptionTracked for changes
options?RecycleBinItemsOptionsuseRecyclebinItems hook optionsPartially
deps?DependencyListHook dependency list.Yes

useRegionalSetting

useRegionalSetting(
  options?: RegionalSettingOptions,
  deps?: any[]): IRegionalSettingsInfo | null | undefined;

Returns site regional settings.

Examples

Get regional settings,

const regionalSettings = useRegionalSetting();

Parameters

NameTypeDescriptionTracked for changes
options?RegionalSettingOptionsuseRegionalSettings hook optionsPartially
deps?DependencyListHook dependency list.Yes

useRoleAssignments

useRoleAssignments(
	options?: RoleAssignmentsOptions,
	deps?: any[]): IRoleAssignmentInfo[] | null | undefined;

Returns role assignmets of selected scope. Use RoleAssignmentsOptions.scope property to change scope. Default is current web.

Examples

Get web role assignments,

const webRolesAssignments = useRoleAssignments();

Get list role assignments,

const myListRoleAssignments = useRoleAssignments({
	scope: {
		list: "5ee53613-bc0f-4b2a-9904-b21afd8431a7"
	}
});

const myListRoleAssignments = useRoleAssignments({
	scope: {
		list: "My List Title"
	}
});

Get item role assignments,

// get list item roles by list title
const listItemRoleAssignments = useRoleAssignments({
	scope: {
		list: "5ee53613-bc0f-4b2a-9904-b21afd8431a7",
		item: 12
	}
});

Parameters

NameTypeDescriptionTracked for changes
options?RoleAssignmentsOptionsuseRoleAssignments hook optionsPartially
deps?DependencyListHook dependency list.Yes

useRoleDefinition

useRoleDefinition(
	roleDefId: string | number,
	options?: RoleDefinitionOptions,
	deps?: any[]): IRoleDefinitionInfo | null | undefined;

Returns role definition with the specified identifier.

Examples

Get role definition,

const roleDefById = useRoleDefinition(1073741826);

const roleDefByName = useRoleDefinition("Contribute");

const roleDefByKind = useRoleDefinition({
	roleType: RoleTypeKind.EditListItems | RoleTypeKind.ManageLists
});

Query role definition properties,

const roleDef = useRoleDefinition({ roleType: RoleTypeKind.EditListItems }, {
	query: {
		select: ["Id", "Name", "Description", "Order"]
	}
});

Parameters

NameTypeDescriptionTracked for changes
roleDefIdstring | numberRole definition name, Id or RoleTypeKindYes
options?WebAppsOptionsuseRoleDefinition hook optionsPartially
deps?DependencyListHook dependency list.Yes

useRoleDefinitions

useRoleDefinitions(
	options?:RoleDefinitionsOptions,
	deps?: any[]): IRoleDefinitionInfo[] | null | undefined;

Returns role definition collection.

Examples

Get all role definitions,

const roleDefByKind = useRoleDefinitions();

Query role definitions

const filteredroleDef = useRoleDefinitions({
	query: {
		select: ["Id", "Name", "Description", "Order"],
		filter: "Hidden eq false"
	}
});

Parameters

NameTypeDescriptionTracked for changes
options?RoleDefinitionsOptionsuseRoleDefinitions hook optionsPartially
deps?DependencyListHook dependency list.Yes

useSearch

useSearch(
        searchQuery: string | ISearchQuery,
        options?: SearchOptions,
        deps?: any[]): [`SpSearchResult` | null | undefined, `GetPageDispatch`]

Conduct search on SharePoint.

Examples

Basic search,

const [results, setPage] = useSearch("search text");

// load next page
setPage(2);

// load page with callback
setPage(3, () => alert("Page Loaded!"));

Advanced search,

const query = {
        Querytext: "*",
        RowLimit: 5,
        RowsPerPage: 5,
        SelectProperties: ["Title"]
};

// Using dependency list to react query property changes.
const [results, setPage] = useSearch(query, undefined, [query?.Querytext]);

Parameters

NameTypeDescriptionTracked for changes
searchQuerystring | ISearchQuerySearch query object or search textYes for string, No for ISearchQuery
options?SearchOptionsuseSearch hook optionsPartially
deps?DependencyListHook dependency list.Yes

useSearchUser

useSearchUser(
	searchOptions: string | IClientPeoplePickerQueryParameters,
	options?: SearchUserOptions,
	deps?: any[]): IPeoplePickerEntity[] | null | undefined;

Searches for users or groups with specified search options.

Examples

Search user by text,

// basic usage
const searchResults = useSearchUser("Mark");

Search user by custom query object,

const query = {
    AllowEmailAddresses: true,
    AllowMultipleEntities: true,
    MaximumEntitySuggestions: 25,
    PrincipalType: PrincipalType.All,
    QueryString: "query text"
};

const searchResults = useSearchUser(query, undefined, [query?.QueryString]);

Parameters

NameTypeDescriptionTracked for changes
searchOptionsstring | IClientPeoplePickerQueryParametersSearch text or query objectYes for string, No for query object
options?SearchUserOptionsuseSearchUser hook optionsPartially
deps?DependencyListHook dependency list.Yes

useSite

useSite(options?: SiteInfoOptions, deps?: any[]): ISiteInfo | null | undefined;

Returns current site info.

Examples

Get site info details,

const siteInfo = useSite();

Query site info details,

const site = useSite({
	query: {
		select: ["Title", "Id"]
	}
});

Parameters

NameTypeDescriptionTracked for changes
options?SiteInfoOptionsuseSite hook optionsPartially
deps?DependencyListHook dependency list.Yes

useSiteUsers

useSiteUsers(
	options?: SiteUsersOptions,
	deps?: any[]): ISiteUserInfo[] | null | undefined;

Returns site users.

Examples

Get all site users,

const siteUsers = useSiteUsers();

Query site users,

const topFiveUser = useSiteUsers({
	query: {
		select: ["Title", "Id", "LoginName"],
		top: 5
	}
});

Parameters

NameTypeDescriptionTracked for changes
options?SiteUsersOptionsuseSiteUsers hook optionsPartially
deps?DependencyListHook dependency list.Yes

useSubWebInfos

useSubWebInfos(
	options?: SubWebsOptions, 
	deps?: any[]): IWebInfosData[] | null | undefined;

Returns web info collection of current webs sub-webs.

Examples

Get all sub sites,

const subSites = useSubWebInfos();

Query sub sites,

const filteredSubSites = useSubWebInfos({
	query: {
		select: ["Title", "Id", "ServerRelativeUrl"],
		filter: "WebTemplate eq 'STS'"
	}
});

Parameters

NameTypeDescriptionTracked for changes
options?SubWebsOptionsuseSubWebs hook optionsPartially
deps?DependencyListHook dependency list.Yes

useUser

useUser(
	userId: string | number,
	options?: UserOptions,
	deps?: any[]): ISiteUserInfo | null | undefined;

Returns an user from site user collection.

Examples

Get site user by Id,

const userById = useUser(27);

Get site user by email,

const userByEmail = useUser("user@example.onmicrosoft.com");

Get site user by login name,

const userByLoginName = useUser("i:0#.f|membership|user@example.onmicrosoft.com");

Query site user properties,

const userById = useUser(27, {
	query: {
		select: ["Id", "Title", "LoginName"]
	}
});

Parameters

NameTypeDescriptionTracked for changes
userstring | numberUser Id, login name or emailYes
options?UserOptionsuseApps hook optionsPartially
deps?DependencyListHook dependency list.Yes

useView

useView(
	listId: string,
	viewId?: string,
	options?: ViewOptions, 
	deps?: any[]): IViewInfo | null | undefined;

Returns a list view.

Parameters

NameTypeDescriptionTracked for changes
listId?stringList UUID or titleYes
viewId?stringView UUID or titleYes
options?ViewOptionsuseView hook optionsPartially
deps?DependencyListHook dependency list.Yes

Examples

Get default list view,

const defaultView = useView("My List Title");

Get list view by name,

const myView = useView("My List Title", "My View");

Get list view by UUID,

const myView = useView("My List Title", "9db07c1f-7880-4601-99d0-1c39c43f6599");

Query default list view properties,

const defaultViewInfo = useView("My List", undefined, {
	query: {
		select: ["Id"]
	}
});

useViews

useViews(
	listId: string,
	options?: ViewsOptions,
	deps?: any[]): IViewInfo[] | null | undefined;

Returns list view collection.

Examples

Get list views,

const allViews = useViews("9db07c1f-7880-4601-99d0-1c39c43f6599");

Query list views,

const viewTitles = useView("My List", {
	query: {
		select: ["Title"],
		top: 5
	}
});

Parameters

NameTypeDescriptionTracked for changes
listIdstringList UUID or titleYes
options?ViewsOptionsuseViews hook optionsPartially
deps?DependencyListHook dependency list.Yes

useWebInfo

useWebInfo(
	options?: WebInfoOptions,
	deps?: any[]): IWebInfo | null | undefined;

Returns current web.

Examples

Get current web info,

const currentWeb = useWebInfo();

Query current web properties,

const currentWeb = useWebInfo({
	query:{
		select: ["Title"]
	}
});

Parameters

NameTypeDescriptionTracked for changes
options?WebInfoOptionsuseWebInfo hook optionsPartially
deps?DependencyListHook dependency list.Yes

useWebProperties

useWebProperties<T>(options?: WebPropertiesOptions, deps?: any[]): T | null | undefined;

Returns webs properties.

Examples

Get web properties,

const webPropertyBag = useWebProperties();

Parameters

NameTypeDescriptionTracked for changes
options?WebPropertiesOptionsuseWebProperties hook optionsPartially
deps?DependencyListHook dependency list.Yes

Building & Testing

Building

pnpm install
pnpm run build

# or use npm

npm install
npm run build

Testing

Test system requires a SharePoint site and app registration on Microsoft identity platform with SharePoint permissions.

After the app registration, create a file named msalSettings.js. You can use msalSettings.example.js as a template or copy the following code snippet.

const privateKey = `
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----`;

const msalInit = {
    auth: {
        authority: "https://login.microsoftonline.com/${TENANT_ID}",
        clientId: "${CLIENT_ID}",
        clientCertificate: {
            thumbprint: "${THUMBPRINT}",
            privateKey: privateKey,
        },
    }
};

export default
    {
        sp: {
            url: "${SITE_URL}",
            msal: {
                init: msalInit,
                scopes: ["${SITE_URL}/.default"]
            },
        },
        graph: {
            msal: {
                init: msalInit,
                scopes: ["https://graph.microsoft.com/.default"]
            },
        }
    };

Replace the following parts in settings file with your own info from app registration:

  • privateKey, replace it with your own certificate private key.
  • ${TENANT_ID}, Your SharePoint tenant UUID.
  • ${CLIENT_ID}, App client UUID.
  • ${SITE_URL}, SharePoint test site URL.
  • ${THUMBPRINT}, Certificate thumbprint.

Most tests use existing info on the site or create simple test cases on-the-fly. Only exceptions are useListItems tests, which require a list called Test List with sizeable (+5000) pre-populated items.

Run npm run test to start vitest when testing environment is ready.

After the first test run, all HTTP responses are cached to node_modules/.prh_cache directory, and tests are replayed from the cached responses whenever there is a match.

CHANGELOG

v2.0.0 - The Wheelwright


Aug 04, 2024

Changed

  • Minimum supported @pnp/sp peer dependency versions has been bumped to ^4.1.0.
  • The library now support React versions between 16.9.0 and ^18.0.0.
  • useSearch, useUserSearch, useChanges object queries are no longer automatically tracked internally. Instead, developers must use the custom dependency list for reactivity just like any other React hooks.
  • Migrated from TypeScript to JavaScript with JSDoc typings, but library still provides type definition files.
  • Migrated from jest to vitest.
  • All dependencies have been updated to their latest versions.
  • useSearch and paged useListItems now provide data as argument on dispatch callbacks.
  • v1's Docusaurus repo has been archived, v2 docs are moved to the main repo.
  • In useListItems paged mode, the hasNext value is inverted to match with the async iterators done property.

Removed

  • useFolderTree hook.
  • RxJs and tslib dependencies have been deleted.

v1.3.0


Apr 22, 2023

Added

  • Site collection and tenant scope option for useApp and useApps hooks.

Changed

  • Minimum supported @pnp/sp peer dependency version bumped to ^3.14.0

v1.2.0


Dec 28, 2022

Added

  • useRecycleBinItem and useRecycleBinItems hooks.
  • createProviderElement helper function for simplifiying SPFx initialization.

Fixed

  • useSearch hook incorrectly overrides RowLimit when getPageDispatch is called.

v1.1.0


May 18, 2022

Added

  • useListItems paged request option.
  • useView and useViews hooks.
  • useListAsStream hook.
  • FetchWithAbort behavior for cancelling fetch requests.

Fixed

  • useSearch initiates double query issue.

v1.0.1


March 11, 2022

Fixed

  • useSearch throwing error when getPageDispatch called more than one.

v1.0.0


March 09, 2022

Initial release