PnP JavaScript library with React JS in SharePoint

In my previous posts, I have given an intro to PnP JS Core library and basic code snippets to access SharePoint objects using PnP-JS-Core component as links follows,

Introduction to PnP-JS-Core

Basic SharePoint web operations using PnP-JS-Core

Filtering SharePoint Object Collections using PnP-JS-Core

After reading the above links, which gives you some basic idea about PnP-JS-Core library and how to use that library in accessing the SharePoint.

Previously, I used PnP-JS-Core library to integrate with Angular JS to show the available sub sites from the parent site.

In this article, I’m going to simulate the same result by using React JS framework to display the sub sites with basic details in a table format.

What are the files required?

React.js A java script library for building user interfaces

React-dom.js React package for working with DOM

Browser.js Enable to compile the java script with xml format with in text/babel to javascript

Pnp.js PnP JavaScript library

Fetch.js Used by PnP js file to handle web requests and responses (Required for IE)

Promise.js Used by PnP js file to handle web requests and responses (Required for IE)

Note: Fetch JS & Promise JS files are required to run PnP methods in some browsers (IE).

Include Script Files:

I have uploaded the required script file under Site Assets library, and added the below lines to our sample html file.

<script type="text/javascript" src="/siteassets/scripts/pnp.min.js"></script>
<script type="text/javascript" src="/siteassets/scripts/fetch.js"></script>
<script type="text/javascript" src="/siteassets/scripts/promise.min.js"></script>
<script type="text/javascript" src="/siteassets/scripts/react.js"></script>
<script type="text/javascript" src="/siteassets/scripts/react-dom.js"></script>
<script type="text/javascript" src="/siteassets/scripts/browser.min.js"></script>

Include HTML:

Add the below css styles to the sample html file. The id with tableContainer is replaced with the with the sub sites table

<!-- To style table in html -->
<style type="text/css">
.web-table th{  background-color:#ddd;  border:2px solid #fff;}
.web-table td{  background-color:#eee;  border:2px solid #fff;}
.web-heading{   padding:2px;}
</style>

<div id='tableContainer'></div>

<script type=’text/babel’>
    <!- - Insert React JSX Code - ->
</script>

Include React JSX:

To create a table with sub site details in rows, we have to create a separate React element for each component

  • Row
  • Table
  • Container
  • Render

Note: Including browser.js file used to compile react jsx lines to javascript

Row component in React JSX

//Create Row component
var ResultItem = React.createClass({
render: function(){
return (
<tr>
<td>{this.props.webTitle} </td>
<td>{this.props.webId} </td>
<td>{this.props.webCreated.toLocaleString()}</td>
<td>{this.props.webTemplate}</td>
</tr>
);
}
});

In table for each row, Adding the <ResultItem> element with attributes within table component’s render method is used to display Web title, Id, created date and template id as an output.

Table component in React JSX

//Create Table component - Within a table component, we have declared the headings for the table
var Results = React.createClass({
render: function(){
var resultItems = this.props.pnpResponse.map(function(result){
return <ResultItem webId={result.Id} webTitle={result.Title} webTemplate={result.WebTemplate} webCreated={new Date(result.Created)} />
});
return(
<table width="100%" cellPadding="10" cellSpacing="2" className="web-table">
<thead>
<tr>
<th>Title</th><th>Id</th><th>Created</th><th>Web Template</th>
</tr>
</thead>
<tbody>{resultItems}</tbody>
</table>
);
}
});

In table component, <Result> element returns the table with hard coded header with dynamic body. {resultItems} used to render the <ResultItem> element with in tbody element, that renders each row based on the initialized property.

Container component in React JSX:

//ShowWebsApp is the parent component, which renders the table and each row component.
var ShowWebsApp = React.createClass({

 getInitialState: function(){
 return{
 pnpResults: []
 }
 },
 
 componentDidMount: function() {
 this.getWebs();
 },
 
 showResults: function(response){
 this.setState({
 pnpResults: response
 })
 },
 
 getWebs: function(){
 $pnp.sp.web.webs.get().then(function(result) {
 this.showResults(result);
 }.bind(this));
 },
 
 render: function(){
 return (

<div> 
 <Results pnpResponse={this.state.pnpResults} />
 </div>

 );
 }
});

<Results> element is the container component and in our example, this is the main component used to interact with PnP-JS-Core library to get the array of sub-sites. Within in this react class getInitialState, componentDidMount, render methods are React functions.

  • getInitialState initializes the array object (pnpResults) to store the web information.
  • componentDidMount method invoked only once and call custom method getWebs(), immediately after the rendering occurs .
  • getWebs method used the pnp javascript method to get the subsite values and store the result to pnpResults array object.
  • render method sets the pnpResults (array of subsites) object to the pnpResponse attribute by using setState react function.

Note: In table component array of pnpResponse value maps the value to each row by calling map function.

Render component in React JSX:

//Render the container component in html element with id “tableContainer”
ReactDOM.render(<ShowWebsApp/>, document.getElementById('tableContainer'));

Full Sample Code:

Insert the below code with in Script Editor or Content Editor web-part.


<script type="text/javascript" src="/siteassets/scripts/pnp.min.js"></script>
<script type="text/javascript" src="/siteassets/scripts/fetch.js"></script>
<script type="text/javascript" src="/siteassets/scripts/promise.min.js"></script>
<script type="text/javascript" src="/siteassets/scripts/react.js"></script>
<script type="text/javascript" src="/siteassets/scripts/react-dom.js"></script>
<script type="text/javascript" src="/siteassets/scripts/browser.min.js"></script>

<!-- To style table in html -->
<style type="text/css">
.web-table th{ background-color:#ddd; border:2px solid #fff;}
.web-table td{ background-color:#eee; border:2px solid #fff;}
.web-heading{ padding:2px;}
</style>

<div id='tableContainer'></div>

<!-- browser.min.js file used to compile and transfer the scripts within text/babel script element to javascript readle for React javascript library -->
<script type="text/babel">
//ShowWebsApp is the parent component, which renders the table and each row component.
var ShowWebsApp = React.createClass({

getInitialState: function(){
return{
pnpResults: []
}
},

componentDidMount: function() {
this.getWebs();
},

showResults: function(response){
this.setState({
pnpResults: response
})
},

getWebs: function(){
$pnp.sp.web.webs.get().then(function(result) {
this.showResults(result);
}.bind(this));
},

render: function(){
return (
<div>
<Results pnpResponse={this.state.pnpResults} />
</div>
);
}
});

//Create Table component - Within a table component, we have declared the headings for the table
var Results = React.createClass({
render: function(){
var resultItems = this.props.pnpResponse.map(function(result){
return <ResultItem webId={result.Id} webTitle={result.Title} webTemplate={result.WebTemplate} webCreated={new Date(result.Created)} />

});
return(
<table width="100%" cellPadding="10" cellSpacing="2" className="web-table">
<thead>
<tr>
<th>Title</th>
<th>Id</th>
<th>Created</th>
<th>Web Template</th>
</tr>
</thead>
<tbody>
{resultItems}
</tbody>
</table>
);
}
});

//Create Row component
var ResultItem = React.createClass({
render: function(){
return (
<tr>
<td>{this.props.webTitle} </td>
<td>{this.props.webId} </td>
<td>{this.props.webCreated.toLocaleString()}</td>
<td>{this.props.webTemplate}</td>
</tr>
);
}
});

//Render the container component in html element with id “tableContainer”
ReactDOM.render(<ShowWebsApp/>, document.getElementById('tableContainer'));
</script>

Output:

Shows website using React JS & PnP-JS-Core
Shows website using React JS & PnP-JS-Core

Conclusion:

This article provides a simple example to lists the sub sites in a table format using React JS framework.

 

3 thoughts on “PnP JavaScript library with React JS in SharePoint

  1. Ofer Reply

    I am getting error:
    browser.min.js:8 Uncaught TypeError: Cannot read property ‘keys’ of undefined
    at Object.n.283.290 (browser.min.js:8)

    And nothing renders

  2. Ofer Reply

    How did you manage to run PNP Core in IE 10?
    I get an error :
    SCRIPT5009: ‘Promise’ is undefined
    File: pnp.min.js, Line: 1, Column: 5224

Leave a Reply

Your email address will not be published. Required fields are marked *