PnPJS is an awesome library that providers wrappers around SharePoint REST API so that we as the developer do not have to write repetitive code and also don't have to worry about details on how to pass headers, data, etc. It is not only limited to SharePoint but we can also use it to call graph and office 365 API. As this library comes as an npm package, it can be used for any node js and javascript-based projects. You can learn more about PnP JS at this link. There are lots of packages available within this library that can be used selectively.
In this article, we will learn to perform list item operations using PnP JS in React-based SPFx solutions, we will see an example of a web part but this can be used in extension in a similar way. This article is to help those who want to get started with SPFx and React and do basic CRUD operations on the SharePoint list which is a very common use case to understand when you want to learn SPFx with React.
Step - Create SPFx Solution
Run below commands in sequence. Open a command prompt and create a directory for the SPFx solution and go to that directory.
md pnpjsoperations
cd pnpjsoperations
Let us now create our solution,
yo @microsoft/sharepoint
Select the below options,
We will be using the React framework here so that we can also explore react concepts. Once you select all options in the wizard one by one, it will take some time to generate the code structure. And you should see a success message once completed.
Step - Install PnP JS Library Package/s
Now let's install the PnPJS npm packages. For this sample, we will be using @sp package so we will only install the sp package but you can install others also based on your requirement. Refer to this link to find a detailed list of packages available within the library.
Run the below command,
npm install @pnp/sp --save
After it is completed, open the same folder in Visual Studio code (you can use any other editor as well).
Now let's modify the code to proceed with the demo. If you want to know about how to get started with React in the SPFx web part, you can check my webinar on same at this link.
Step - Passing Web part Context to React Component
PnP JS Sharepoint site context to work with, therefore we will pass it from our web part file to react components.
Open src\webparts\controls\components\ISampleDemoProps.ts
Modify the code as below,
import { WebPartContext } from "@microsoft/sp-webpart-base";
export interface ISampleDemoProps {
description: string;
spcontext:WebPartContext;
}
Open src\webparts\controls\ControlsWebPart.ts.
Modify the render method to pass the context.
public render(): void {
const element: React.ReactElement<ISampleDemoProps> = React.createElement(
SampleDemo,
{
description: this.properties.description,
spcontext:this.context
}
);
ReactDom.render(element, this.domElement);
}
Please note we have just added the line ‘spcontext:this.context’ .
Step - Modify React Component
Below are the high-level steps that we will do.
- Import required library, in our case, we will be using the PnP package and buttons from office UI fabric react.
- Create a state interface, properties will be used to control showing/hiding message bar, its message, and ItemID of the new item created.
- Constructor to initialize PnP JS context and state.
- The render method has been modified to add 4 buttons to demonstrate the respective use case.
- 4 methods are called based on targeted button selection.
- Calling PnP JS methods and modifying message and showing message bar.
Open src\webparts\controls\components\SampleDemo.tsx
import * as React from 'react';
import styles from './SampleDemo.module.scss';
import { ISampleDemoProps } from './ISampleDemoProps';
import { escape } from '@microsoft/sp-lodash-subset';
//import library
import { PrimaryButton, Stack,MessageBar, MessageBarType } from 'office-ui-fabric-react';
import { sp, IItemAddResult, DateTimeFieldFormatType } from "@pnp/sp/presets/all";
//create state
export interface ISampleDemoState {
showmessageBar:boolean; //to show/hide message bar on success
message:string; // what message to be displayed in message bar
itemID:number; // current item ID after create new item is clicked
}
export default class SampleDemo extends React.Component<ISampleDemoProps, ISampleDemoState> {
// constructor to intialize state and pnp sp object.
constructor(props: ISampleDemoProps,state:ISampleDemoState) {
super(props);
this.state = {showmessageBar:false,message:"",itemID:0};
sp.setup({
spfxContext: this.props.spcontext
});
}
public render(): React.ReactElement<ISampleDemoProps> {
return (
<div className={ styles.sampleDemo }>
<div className={ styles.container }>
<div className={ styles.row }>
<div className={ styles.column }>
<span className={ styles.title }>Welcome to PnP JS List Items Operations Demo!</span>
</div>
</div>
</div>
<br></br>
<br></br>
<Stack horizontal tokens={{childrenGap:40}}>
<PrimaryButton text="Create New Item" onClick={()=>this.createNewItem()} />
<PrimaryButton text="Get Item" onClick={()=>this.getItem()} />
<PrimaryButton text="Update Item" onClick={()=>this.updateItem()} />
<PrimaryButton text="Delete Item" onClick={()=>this.delteItem()} />
</Stack>
<br></br>
<br></br>
{this.state.showmessageBar &&
<MessageBar onDismiss={()=>this.setState({showmessageBar:false})}
dismissButtonAriaLabel="Close">
{this.state.message}
</MessageBar>
}
</div>
);
}
// method to use pnp objects and create new item
private async createNewItem(){
const iar: IItemAddResult = await sp.web.lists.getByTitle("DemoList").items.add({
Title: "Title " + new Date(),
Description: "This is item created using PnP JS"
});
console.log(iar);
this.setState({showmessageBar:true,message:"Item Added Sucessfully",itemID:iar.data.Id});
}
// method to use pnp objects and get item by id, using item ID set from createNewItem method.
private async getItem(){
// get a specific item by id
const item: any = await sp.web.lists.getByTitle("DemoList").items.getById(this.state.itemID).get();
console.log(item);
this.setState({showmessageBar:true,message:"Last Item Created Title:--> " + item.Title});
}
// method to use pnp object udpate item by id, using item id set from createNewItem method.
private async updateItem(){
let list = sp.web.lists.getByTitle("DemoList");
const i = await list.items.getById(this.state.itemID).update({
Title: "My Updated Title",
Description: "Here is a updated description"
});
console.log(i);
this.setState({showmessageBar:true,message:"Item updated sucessfully"});
}
// method to use pnp object udpate item by id, using item id set from createNewItem method.
private async delteItem(){
let list = sp.web.lists.getByTitle("DemoList");
var res = await list.items.getById(this.state.itemID).delete();
console.log(res);
this.setState({showmessageBar:true,message:"Item deleted sucessfully"});
}
}
For understanding purposes, I have added comments in the above code.
Step - Testing the webpart
Let us see this web part in the action.
Run gulp serve,
gulp serve
Open the SharePoint workbench page.
https://spevents.com/sites/spsahmd2019/_layouts/15/workbench.aspx
Add a target web part, and when the page loads, we will see the below output,
Click on Create New Item.
Below is an entry added to my Demo List.
Click on Get-Item.
Click on Update Item.
Updated entry in demo list.
Click on Delete item.
We can see in the list entry is deleted.
Conclusion
We have seen the basic use cases on how-to-do list items operations with PnP JS and React. I would suggest looking at the usage of state to show the hiding message bar and dynamic text in the message bar. This is a very common use case we will have to do for showing success/failure messages for custom forms in SPFx.
I hope this helps...Happy coding...!!!