Understanding the Changes in PnPjs: Handling the Removal of IItemAddResult and Using the Latest Version

With the latest updates to PnPjs (version 2.x and beyond), there have been some changes that impact how developers interact with SharePoint list items, particularly when creating new items. One such change is the removal of the IItemAddResult interface, which was previously used to type the result of adding a new item to a SharePoint list.

In this article, we will explain:

  1. What was IItemAddResult?
  2. Why was it removed?
  3. How to adapt your code without IItemAddResult
  4. A complete example with the correct modern approach

1. What Was IItemAddResult?

Before the recent updates in PnPjs, IItemAddResult was an interface used to define the structure of the response when an item was added to a SharePoint list using PnPjs. It provided type definitions for the response, making it easier to handle the result in TypeScript projects.

In previous versions, you might have seen code like this:

import { IItemAddResult } from "@pnp/sp/items";

const addItem = async () => {
  const list = sp.web.lists.getByTitle("MyList");
  const result: IItemAddResult = await list.items.add({
    Title: "New Item",
    Description: "This is a description"
  });
  console.log(result);
};
  • IItemAddResult: This interface provided a structured response from the add method, typically including details about the newly added item.

2. Why Was IItemAddResult Removed?

With the evolution of PnPjs, the library was updated to simplify its API and make it easier for developers to use, regardless of the changing structure of the SharePoint REST API. This resulted in some refactoring of the internal type definitions, including the removal of IItemAddResult.

Key reasons for this change include:

  • Dynamic Typing: The PnPjs team opted to rely on dynamic types returned by API calls, which allows for more flexibility when working with the library.
  • Simplicity: Removing specific interfaces like IItemAddResult reduces the need for rigid type checking, especially as the structure of SharePoint responses may vary based on custom fields, list settings, etc.
  • Forward Compatibility: This approach helps ensure that the library remains compatible with future changes in SharePoint, as the structure of the returned data may evolve.

3. How to Adapt Your Code Without IItemAddResult

Even though IItemAddResult has been removed, you can still retrieve the same information from the add method’s response, which now returns a dynamic object. The modern approach involves directly working with the returned object without relying on a specific type.

Here’s how you can update your code to work with the current version of PnPjs:

import { spfi, SPFx } from "@pnp/sp";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";

export default class MyWebPart extends BaseClientSideWebPart<{}> {

  private sp;

  public onInit(): Promise<void> {
    return super.onInit().then(_ => {
      this.sp = spfi().using(SPFx(this.context));
    });
  }

  private async addItem() {
    try {
      const list = this.sp.web.lists.getByTitle("MyList");
      const result = await list.items.add({
        Title: "New Item",
        Description: "This is a new item"
      });
      console.log(result); // You can access the result object directly
    } catch (error) {
      console.error("Error adding item:", error);
    }
  }
}

In this example:

  • We removed the IItemAddResult import.
  • Instead of explicitly typing the result, we dynamically access the response returned by the add() method.

This dynamic object will still contain information about the newly added item. You can access the data using result.data or other properties depending on what you need.

Example Accessing Item Data:

console.log(result.data); // Contains the newly added item's data

4. A Complete Example with All CRUD Operations

To give you a full picture, here’s how you can implement all CRUD operations (Create, Read, Update, and Delete) on SharePoint list items using the latest PnPjs version, without relying on IItemAddResult:

import { spfi, SPFx } from "@pnp/sp";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";

export default class MyWebPart extends BaseClientSideWebPart<{}> {

  private sp;

  public onInit(): Promise<void> {
    return super.onInit().then(_ => {
      this.sp = spfi().using(SPFx(this.context));
    });
  }

  // Add a new item
  private async addItem() {
    try {
      const list = this.sp.web.lists.getByTitle("MyList");
      const result = await list.items.add({
        Title: "New Item",
        Description: "This is a new item"
      });
      console.log(result.data); // Access newly added item's data
    } catch (error) {
      console.error("Error adding item:", error);
    }
  }

  // Get all items
  private async getItems() {
    try {
      const items = await this.sp.web.lists.getByTitle("MyList").items.select("Title", "Description").get();
      console.log(items);
    } catch (error) {
      console.error("Error retrieving items:", error);
    }
  }

  // Update an item
  private async updateItem(itemId: number) {
    try {
      const item = await this.sp.web.lists.getByTitle("MyList").items.getById(itemId).update({
        Title: "Updated Title"
      });
      console.log(item);
    } catch (error) {
      console.error("Error updating item:", error);
    }
  }

  // Delete an item
  private async deleteItem(itemId: number) {
    try {
      await this.sp.web.lists.getByTitle("MyList").items.getById(itemId).delete();
      console.log(`Item with ID ${itemId} deleted`);
    } catch (error) {
      console.error("Error deleting item:", error);
    }
  }

  public render(): React.ReactElement<{}> {
    return (
      <div>
        <button onClick={() => this.addItem()}>Add Item</button>
        <button onClick={() => this.getItems()}>Get Items</button>
        <button onClick={() => this.updateItem(1)}>Update Item</button>
        <button onClick={() => this.deleteItem(1)}>Delete Item</button>
      </div>
    );
  }
}

In this example:

  • We perform all CRUD operations using the latest version of PnPjs.
  • Dynamic typing is used for the result of each operation, eliminating the need for specific interfaces like IItemAddResult.

5. Conclusion

The removal of IItemAddResult in PnPjs is part of the library’s effort to streamline its API and make it more flexible. Although IItemAddResult is no longer available, you can still retrieve and manipulate the result of SharePoint list operations dynamically. By updating your code as shown in this article, you’ll be fully aligned with the latest PnPjs practices and able to work efficiently with SharePoint list items.

Edvaldo Guimrães Filho Avatar

Published by

Categories:

One response to “Understanding the Changes in PnPjs: Handling the Removal of IItemAddResult and Using the Latest Version”

  1. Miroslav Navratil Avatar
    Miroslav Navratil

    Thank you for sharing

    Liked by 1 person

Leave a comment