Monday, 15 September 2025

SharePoint Framework (SPFx) React WebPart lifecycle

In this blog, we will be learning about the lifecycle event of SharePoint Framework (SPFx) web part with React.

What is a web part?

A web part is a reusable visual object that a page author can add to their content, and customize using a property pane.


In SPFx web parts the lifecycle refers to the sequence of events or methods that are executed during the web part's initialization, rendering, and disposal. The SPFx web part lifecycle integrates both core SPFx methods and the standard React component lifecycle methods.

When building a SPFx web part using React, two lifecycles are involved:
  • SPFx WebPart Lifecycle
  • React Component Lifecycle

I have created a simple react based webpart which displays logged-in user name and webpart edit property. On button click the number gets incremented by one.


SPFx WebPart Lifecycle

The SPFx framework has its own lifecycle methods for the web part class (instance) in the .ts file, which interact with the React Component.

Web part Base Class - defines the main entry point for the web part. Extends the BaseClientSideWebPart. All client-side web parts must extend the BaseClientSideWebPart class to be defined as a valid web part.

export default class SpFxWebpartLifecycleWebPart extends BaseClientSideWebPart <ISpFxWebpartLifecycleWebPartProps>

BaseClientSideWebPart class - This abstract class implements the base functionality for a client-side web part. Every client-side web part needs to inherit from this class.
Extends BaseWebPart<TProperties>

Along with the base functionality, this class provides some APIs that can be used by the web part. These APIs fall in two categories.

The first category of APIs provide data and functionality. Example, the web part context (i.e. this.context). This API should be used to access contextual data relevant to this web part instance.

The second category of APIs provide a base implementation for the web part lifecycle and can be overridden for an updated implementation. The render() API is the only API that is mandatory to be implemented/overridden by a web part. All other life cycle APIs have a base implementation and can be overridden based on the needs of the web part.

The main SPFx lifecycle methods are:
SPFx Method Purpose
constructor() Constructor for the BaseClientSideWebPart class.
Initialize the web part class (services, variables). React is not yet mounted.
onInit() This event method is called when the web part is initialized.
Returns a Promise. Use it for async initialization (fetching data, setting context).
render() This API is called to render the web part. There is no base implementation of this API and the web part is required to override this API.
Creates and renders the React component in DOM with ReactDom.render().
onDispose() This API should be used to refresh the contents of the PropertyPane.
Cleanup (unmount React with ReactDom.unmountComponentAtNode). Called when the web part is removed from the page.

You can find SPFx lifecycle Properties and Methods detail here


React Component Lifecycle

Within the main SPFx web part render method, a React component is mounted. This component is defined in .tsx file which follows its own lifecycle.

React.Component - Component is the base class for the React components defined as JavaScript classes. To define a React component as a class, extend the built-in Component class and define a render method. Only the render method is required, other methods are optional.

export default class SpFxWebpartLifecycle extends React.Component<ISpFxWebpartLifecycleProps, ISpFxWebpartLifecycleState>


The main React component lifecycle methods are:
React Method Purpose
constructor() Initialize state and bind event handlers
render() Returns the JSX/TSX (UI structure) to be rendered
componentDidMount() Called after the component is inserted into the DOM. This is the ideal place for API calls to fetch data from sources like SharePoint lists.
shouldComponentUpdate(nextProps, nextState, nextContext) To optimize the re-rendering process by allowing React to skip the re-render if props or state has changed.
componentDidUpdate(prevProps, prevState, snapshot?) Called after the component’s props or state have been updated. Use this to perform side effects or re-fetch data based on specific prop/state changes.
componentWillUnmount() Called just before the component is removed from the DOM. Essential for clean-up of resources, such as removing event listeners or cancelling network requests.

You can find React Component methods here



In the SPFx react webpart the methods are defined and a console log statement is added to track the webpart lifecycle flow.
Lets add a webpart on the page and check the behavior.

Event: Page load
On Page load the webpart is displayed. The both SPFx lifecycle and React component lifecycle events are triggered.




Event: Button click/State change
Click on the "Increment My Number" button and this will increment the number by 1 on every click. Here state value gets updated. React responds to state/prop changes by re-rendering react component. The SPFx lifecycle events will not get executed and only React component lifecycle events are triggered.





Event: Page edit mode
The both SPFx lifecycle and React component lifecycle events are triggered.
This event first removes/disposes the webpart component. The SPFx onDispose method simply calls ReactDom method ReactDom.unmountComponentAtNode(this.domElement) - it removes a mounted React component from the DOM and clean up its event handlers and state.
In addition, unmounting a component also triggers the React componentWillUnmount() lifecycle method. This method is often used to perform any necessary cleanup, such as invalidating timers, canceling network requests, or cleaning up any subscriptions that were created in componentDidMount.

protected onDispose(): void {   
   ReactDom.unmountComponentAtNode(this.domElement);
}

Once the webpart component is unmounted then again the webpart is rendered and mounted. Here the lifecycle is similar to the page load event.




Event: Edit WebPart/Open Property Pane
On editing webpart properties (opening property pane) - only the SPFx lifecycle events are triggered.

The loadPropertyPaneResources() method only gets called once. If you close the property pane and re-open then this method will not get call. It will only be called again if you reload the page and then open property pane.
The getPropertyPaneConfiguration() method will get executed twice. It's happening because of the reactive property pane interaction mode. When a property value changes (e.g. in a PropertyPaneTextField), the framework often re-evaluates the entire property pane configuration to determine if other fields need to be updated, hidden, shown, or disabled based on the new value.




Event: WebPart Property Pane closed
When webpart property pane is closed SPFx onPropertyPaneConfigurationComplete() method is called. This method will be trigger whether properties are changed or not. Only one SPFx lifecycle event is triggered.




Event: WebPart property change
When property pane field value changes. SPFx detects property changes and updates the web part. React responds to state/prop changes by re-rendering react component. The both SPFx lifecycle and React component lifecycle events are triggered.
The getPropertyPaneConfiguration() and onPropertyPaneRendered() method will get executed twice. It's happening because of the reactive property pane interaction mode. The default behavior is Reactive.







I hope this will help all of you! 🧲
Feel free to provide feedback.


🚀 "Happy Coding" 🚀

Tuesday, 10 June 2025

Get SharePoint search results using the Rest API in PowerAutomate

In this blog, we will be learning about how to get SharePoint search results using the Rest API through PowerAutomate flow. The search results will be exported into a CSV file and saved into a SharePoint library. 

Create Flow

1). Sign in to Power Automate

2). Open the flow, click on the Create option, and select "Instant Cloud Flow".

Enter Flow name.
Choose the flow trigger as "Manually trigger a flow".
Click on the Create button.



3). Add an action "Send an HTTP request to SharePoint".


Site Address
https://yoursite.sharepoint.com/sites/VideoHub
Method
GET
Uri
_api/search/query
?querytext='Path:https://yoursite.sharepoint.com/sites/VideoHub*'
&trimduplicates=false&rowlimit=500
&selectproperties='Title,RefinableString00,RefinableInt00,
                   IsDiscontinued,RefinableString03'
&refiners='contentclass,SecondaryFileExtension,ListID'
&refinementfilters='and(
    contentclass:equals("STS_ListItem_DocumentLibrary"),
    SecondaryFileExtension:or("mp4","mkv"),
    ListID:equals("f7fb8ca6-aaaa-bbbb-cccc-7816d24bdf42")
)'
&sortlist='Created:descending'
Headers
{
  "accept": "application/json; odata=nometadata"
}


4). Add an action "Parse JSON" and enter output of previous step in Content.
In the Schema field use the below JSON content.


Parse JSON - Schema

		

Add additional type null - this will take care of the null values coming in search results.


5). Initialize variables one of type Object and Array.


		


6). Add "Apply to each" loop for rows and enter step 4 output (or enter below) as input value.

body('ParseJSONtoGetRows')['PrimaryQueryResult']['RelevantResults']['Table']['Rows']

Add another nested "Apply to each" loop for cells and enter current cells value (or enter below) as input value.

items('Apply_to_each-Rows')['Cells']


7). Add a "Switch" condition and enter current cell key value (or enter below) as On value.

items('Apply_to_each-Cells')?['Key']


8). Add a case statement to fetch field value from the search property.

Enter search managed property Title in equals field.

Add an action "Compose" and add below value in the inputs parameter.

setProperty(variables('varResponseJson'),'Title',items('Apply_to_each-Cells')?['Value'])

Here, setProperty(object, property, value) function is used; it returns an object with a property set to the provided value.

Add an action "Set variable" (defined in step 5) object variable and enter previous step output as input value.

9). Add more case statements; we are fetching five field values from the search properties. Therefore, five case statements are needed.
Repeat the step 8 for all the required search managed property.

Note: Create search managed properties for your custom fields and use them.




10). Append the array variable (defined in step 5) and enter object variable output as value after closing on inner "Apply to each" loop.


11). Add an action "Create CSV table" and enter array variable in From and Automatic in Columns.


12). Add an action "Create file" to create CSV file to export the search results.

Enter the Site Address and Folder Path as required.

File Name as concat('BlogData_', formatDateTime(utcNow(), 'yyyyMMdd_HHmmss'), '.csv')

File Content as output from previous step 12.



I hope this will help all of you! 🧲
Feel free to provide feedback.


🚀 "Happy Coding" 🚀

Monday, 10 February 2025

Get ServiceNow incident data using OAuth in Postman

In this blog, we will be learning about how to get ServiceNow incident ticket details using OAuth authentication in Postman.

Please follow the below steps:

Register OAuth application in ServiceNow

Before using OAuth in Postman, we must set up an OAuth provider in ServiceNow. Here's how to do that:

1). Log in to your ServiceNow instance as an administrator.
2). Open System OAuth > Application Registry.



3). Click on New and select Create an OAuth API endpoint for external clients.


4). Fill in the necessary fields:

Name: A descriptive name - "Postman OAuth App".
Client ID: A unique identifier for your application.
Client Secret: A secret key generated for your app.


5). Save the record and take note of the Client ID and Client Secret as you'll need them in Postman.

Get OAuth Token in Postman

Once your OAuth application is registered in ServiceNow, you'll use it to obtain an access token in Postman.

1). Open Postman.
2). Set the HTTP Method to POST.
3). Request URL is https://dev29xxxx.service-now.com/oauth_token.do
4). Go to the Body tab.
5). Fill in the details:

Key Value
grant_type password
client_id 58au69vbbe3771xxx2ab5793c46cd2xxxbb
client_secret Vb!2,69C5V|fAU
username admin
password AwdVmIseR4h*J4@

6). Click Send button to obtain the token.


Make a Request to Get Incident Data

1). Open Postman.
2). Set the HTTP Method to GET.
3). Request URL is:

https://dev29xxxx.service-now.com/api/now/table/incident?sysparm_limit=5&sysparm_query=active=true^ORDERBYDESCnumber&caller_id.email=david.miller@example.com&sysparm_fields=number,sys_created_on,urgency,state,short_description

4). Go to the Headers tab.
5). Fill in the details:

Key Value
Content-Type application/json
Accept application/json
Access-Control-Allow-Origin *
Authorization Bearer [access_token_value]

6). Click Send button to obtain the token.


View the Response

If everything is configured correctly, Postman will return a JSON response with the incident data from ServiceNow.


I hope this will help all of you! 🧲
Feel free to provide feedback.

Thursday, 2 January 2025

Migrate from an existing Run As Account to Managed identities

In this blog, we will be learning about migrating from an existing 'Run As Accounts' to Managed identities.

Sign in to the Azure portal with an account that’s a member of the subscription Administrator role or a Co-Administrator of the subscription.

The managed identities are of two types system assigned or user assigned.


Steps to be followed to migrate an existing 'Run As Accounts' to Managed identities:

Step 1: Identify the 'Run as accounts' getting expired.


Step 2: Check current role assignments for 'Run as account'.

Click on Run As Account from the screen above, it will show properties of it and at the bottom it will list out the roles.


Step 3: Create System Assigned Managed Identity.

Now we need to create the Managed Identity to migrate to. Go to the Automation Account and select Identity in the left navigation. It will allow to create a new System assigned, or User assigned managed identity.

Create a new System assigned managed identity. Click On and save it, Azure will automatically create the managed identity.


Once it finishes creating the managed identity, we can see the Object ID. Now, we can begin assigning permissions.


Step 4: Assign permissions to Managed Identity.

Click on Azure Role Assignments on the newly created managed identity. Add the same permissions (Step 2) as existing RunAs account had.


Once finished, we can see the role assignments assigned to the new managed identity (it will take some time to display roles assigned).


Step 5: Update credentials

Go to the Automation Account and select Credentials in the left navigation.


Select and update the Password and Confirm Password with App Secret value.
(Open App Registrations and create new client secret. Copy the client secret value and use it above)

Select Save.



⊛ Note

No need to do any changes in the Runbook code to use managed identities.


Step 6: Delete the 'Run As Account'

The final task is to clean up the RunAs resources. Go to the 'Automation Account' > 'Run As Accounts' and then click Delete.


Once finished, we will see that our existing automation account no longer has any Run As Accounts tied to it. It will also be deleted from the Azure Active Directory (AAD).



Refer Microsoft documentation for more
https://learn.microsoft.com/en-us/azure/automation/migrate-run-as-accounts-managed-identity


I hope this will help all of you! 🧲
Feel free to provide feedback.


Wednesday, 16 October 2024

Adaptive Card: Send Form using Adaptive card in MS Teams to group members

In this blog, we will be learning about Adaptive Cards and how to send an adaptive card Form in MS Team's chat and get response details.

Our business scenario involves obtaining project status details from project leads on a monthly basis. Previously, these updates were collected via email and manually recorded in an Excel file. Now, we have implemented a more efficient solution: project status updates can be submitted directly within MS Teams using- an Adaptive Card, and the information is automatically saved into a SharePoint list.

Here, we will be creating two Power Automate flows:

  • To send Adaptive card in MS Teams to group members
  • To get project status using Adaptive card

Create Flow

1). Sign in to Power Automate

2). Open the flow, click on the Create option, and select "Scheduled Cloud Flow".

Enter Flow name.
Set the flow recurrence interval as monthly.
Click on the Create button.


3). Add an action "List group members" and enter team name from the dropdown in Group Id parameter. Its used to get all the members details present in the teams in an array.


4). Add "Apply to each" loop and enter previous step output value as input value.

5). Add an action "HTTP" and enter the parameter values as per table. The URI value will be generated automatically in the second flow in step 8.


Method POST
URI https://prod-99.india.logic.azure.com:443/workflows ...
Headers
{
  "Content-Type": "application/json"
}
Body
{
  "email": mail_value_from_ListGroupMembers
}
Authentication None

6). The first complete flow with all the actions will look like below.



7). Create another flow, click on the Create option, and select "Automated Cloud Flow".

Enter Flow name.
Choose the flow trigger as "When a HTTP request is received". The trigger is not directly available.
So, click on the Skip button.


Now in the Power Automate flow designer search for the flow trigger again. Here, you will find it.


8). In the trigger set the parameter values as shown below.

HTTP POST URL will be generated automatically and will be used in step 5

{
    "type""object",
    "properties": {
        "email": {
            "type""string"
        }
    }
}



9). Now, add an action "Post adaptive card and wait for a response".

Add mandatory parameter values as shown in below image. Refer step 11 for details.


10). Add an action "Get user profile (V2)" and enter User (UPN) value as project manager dynamic value from above step.

Then, add "Create item" action to save the record in the SharePoint list.





Now we will discuss how to create Adaptive Card parameter value.

11). Open Adaptive Cards Designer portal.

Select host app as "Microsoft Teams" and Target version as 1.4
Then, create the Adaptive card design according to your requirements.

Once Adaptive Card design is complete. Click on "Copy card payload" and paste it into the Adaptive Card parameter value (Step 9).

The Id property of an element or control is crucial, as its utilized when accessing control values within a flow.

Get project status using Adaptive card - CARD PAYLOAD
{
  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.4",
  "id": "myProjectACE",
  "body": [
    {
      "type": "TextBlock",
      "text": "Project Status Details",
      "wrap": true,
      "id": "applicationHeader",
      "size": "ExtraLarge",
      "weight": "Bolder",
      "color": "Default",
      "horizontalAlignment": "Center",
      "separator": true
    },
    {
      "type": "Image",
      "url": "https://cdn4.iconfinder.com/data/icons/alter-3d-scenes/256/business___
	  graph_chart_analytics_statistics_presentation_project_3d_people2x.png",
      "id": "projectImage",
      "separator": true,
      "horizontalAlignment": "Center"
    },
    {
      "type": "TextBlock",
      "text": "Kindly complete this form",
      "wrap": true,
      "separator": true,
      "size": "Large",
      "color": "Dark",
      "horizontalAlignment": "Left",
      "fontType": "Default",
      "weight": "Default",
      "id": "formHeader"
    },
    {
      "type": "Input.Text",
      "id": "projectName",
      "label": "Project Name",
      "isRequired": true,
      "errorMessage": "This is required"
    },
    {
      "type": "ColumnSet",
      "columns": [
        {
          "type": "Column",
          "width": "stretch",
          "items": [
            {
              "type": "Input.Text",
              "id": "projectCode",
              "isRequired": true,
              "label": "Project Code",
              "errorMessage": "This is required"
            },
            {
              "type": "Input.Date",
              "id": "startDate",
              "label": "Start Date"
            }
          ]
        },
        {
          "type": "Column",
          "width": "stretch",
          "items": [
            {
              "type": "Input.Text",
              "id": "teamSize",
              "label": "Team Size"
            },
            {
              "type": "Input.Date",
              "id": "endDate",
              "label": "End Date"
            }
          ]
        }
      ],
      "id": "projectColumnSet"
    },
    {
      "type": "Input.ChoiceSet",
      "choices": [
        {
          "title": "Active: The project is currently being worked on by the project team",
          "value": "Active: The project is currently being worked on by the project team"
        },
        {
          "title": "Completed: Work on the project has finished, and all deliverables/tasks
                    have been completed",
          "value": "Completed: Work on the project has finished, and all deliverables/tasks
                    have been completed"
        },
        {
          "title": "Cancelled: The project has not finished, and work on the project will
                    not continue",
          "value": "Cancelled: The project has not finished, and work on the project will
                    not continue"
        },
        {
          "title": "On Hold: The project has not finished, and work on the project has
                    been temporarily suspended",
          "value": "On Hold: The project has not finished, and work on the project has
                    been temporarily suspended"
        }
      ],
      "id": "projectStatus",
      "label": "Project Status",
      "isRequired": true,
      "errorMessage": "This is required"
    },
    {
      "type": "Input.ChoiceSet",
      "choices.data": {
        "type": "Data.Query",
        "dataset": "graph.microsoft.com/users"
      },
      "id": "projectManager",
      "label": "Project Manager / Account Manager",
      "isRequired": true,
      "errorMessage": "This is required",
      "isMultiSelect": false
    },
    {
      "type": "Input.Text",
      "isMultiline": true,
      "id": "comments",
      "label": "Comments(if any)"
    },
    {
      "type": "Input.Toggle",
      "title": "I accept the terms and agreements",
      "id": "acceptTerms",
      "isRequired": true,
      "errorMessage": "You must accept the terms to continue.",
      "label": "Please check the box below to accept the terms and agreements:"
    }
  ],
  "actions": [
    {
      "type": "Action.Submit",
      "title": "Save",
      "id": "save",
      "iconUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXN
	  SR0IArs4c6QAAAhhJREFUOE9jZKAyYKSyeQwoBprMuO3/n4FBg+/XG9cYAyElXoYffDALX//jfoNs+ZpLr59
	  8ZxVIOZGp+QBZHG6gybTbfgxMDBtBkmK/XjD0eEkxPHjyBK7WzMAAxTNxiy4xvGSTfMD6/7cjsqEIA2fermf
	  4z9AAM7DVVZTh2LlzcEPCvb0xDHzFJsHwn4ERxVCEgdNvNzAwMtSDdDF/eMSwLEaT4eylSwx//v1lEODlYzD
	  T14Mb+OvPP4aA2ecY/gnKQcT+MzSeyVQFOwargd/fPmUwleZkcNcQYWBhZkJx2Z+//xh2Xn/NcObZDwYOYWn,
	  cBhpNvDqPiZ0tEWzhvz8Mf75/Yfj/7x/WRMDIxMzAwsnDAKJB4N/PX/PP5WsnobhQr//8ATZOHntyktGv718
	  OXio0dKCvgRI8zAy8bNjT/edf/xlefPmLiCRCLsw14WXwVuHE6/stt78zTDn7GayGoJc3h4ky/P31i+Hjp09
	  YDeXn42NgZmNj8F31mjgDd0SIMfz+/Yfh67dvWA3k5uJiYGVlYfBY8Yp4Az9/+crw7PkLrAZKSUow8PJw4zd
	  Qv/fMelZu/gCQCSAXEgNgLvz59eP6y8UmQSjJRrd5TwAjB+96ZlZ2hkYbbmLMY6g/8pXh7+8fDH9/fPK/Wuu
	  2CcVAEEejcacvw///FolanEQl8PnXvh9kYGA8fqPBfQvMBbQtYInyJwFFAGUS8BXW+cfxAAAAAElFTkSuQmCC"
    }
  ]
}



12). The second complete flow with all the actions will look like below.



Now it's time to test the flow. Manually run the flow and wait for sometime.

Project Status form in Adaptive Card output for Teams web application.






Fill out the form and click Save button. Error message will be shown if mandatory fields are not filled.


Check the second flow history and move to action "Post adaptive card and wait for a response".

Open "Show raw outputs" and you can see that the saved form response is in the data node.

People Picker in Adaptive card returns the Microsoft Entra ID (Azure Active Directory) of the user selected. Due to that the user details are fetched using "Get user profile (V2)" action and its output is used.




Refer Adaptive Card blog series:
Adaptive Card: Power Automate send welcome message when new team member added
Adaptive Card: Power Automate send birthday greetings to team members
People Picker in Adaptive Cards
Adaptive Card: Send Form using Adaptive card in MS Teams to group members


I hope this will help all of you! 🧲
Feel free to provide feedback.


🚀 "Happy Coding" 🚀