Previously, I went over the setup and compilation steps needed to launch a React app in a Persona Bar extension. Now, I want to go under the hood and explain the inner wiring between Persona Bar and the app itself.
Useful Blogs
Before we proceed, you may want to reference these blogs:
-
DNN 9: Persona Bar Architecture
-
DNN 9: Extending the Persona Bar
-
DNN9: Adding a ReactJS App to Persona Bar
Standard extension vs. React extension
We will now highlight the differences between the standard extension and a React extension. To start with, the main Html and JavaScript files are different. There is an entire new application.web (replace application with your app's name) folder in the source code repository containing code for React.
Difference in Html
The old Html had a standard div containing a line of plain text. This text was printed "as is" on the canvas. We will replace the div with a new one. The new div has only one attributes, id with a value helloworld-container.
We will dig into this id very soon, let's look into JavaScript for now.
Difference in JavaScript
The JavaScript has more changes than the Html file.
Change in parameters
We pass a different parameter - '$'. This is jQuery, which is used later to make an ajax call.
Change in init method
The init method calls a new method loadScript.
1
2
3
|
init: function (wrapper, util, params, callback) {
loadScript();
},
|
New loadScrpt method
The LoadScript method loads the bundle.js file via ajax. Note the path of the bundle file, it is scripts/bundles/ folder.
1
2
3
4
5
6
7
8
|
function loadScript() {
var url = "scripts/bundles/helloworld-bundle.js";
$.ajax({
dataType: "script",
cache: true,
url: url
});
}
|
Search for "hello" in the folder
The next step is to dig deeper into the React code base. Some of the code is just boiler plate, and some are specific to this extension. It's a always a good idea to search for hello in the folder HelloWorld.Web and see how many hits we get. We found 4 files. Let's get into them one by one.
webpack.config.js
Besides other information, this file also stores the name of the output bundle file that gets created after build is completed. This is where helloworld-bundle.js is found.
package.json
This file stores the name of the package that you are building. You can use the name helloworld to reference it as a component in another React app.
main.jsx
Main.jsx is the starting point for this application. A React app needs a div (or container) to attach itself to. Recall that we defined a div in the main html file. It's id was helloworld-container. This is what we will hook React to. React will automatically render itself here.
App.jsx
Even though Main.jsx is the starting point, the real app starts from App.Jsx. Most of the React file contains a function render, which is responsible for generating the Html content. All we are doing here is putting a title "Hello World", using one of the DNN's common component named SocialPanelHeader.
This component is further wrapped around another DNN common component PersonaBarPage.
Relationship between Webpack and Package
Webpack.config.js defines a constant webpackExternals, which references dnn-webpack-externals component defined in Package.json. The entire common component set is actually made available at run time in the browser by Persona Bar core. However, this relationship must be defined in this specific way for your React source to be compiled and a bundle created.
Common Components
The DNN team has built several common React components to be used in Persona Bar extension. The source code for such components can be found here: https://github.com/dnnsoftware/Dnn.React.Common.
Using Common React Components in extensions
We have two main common components that you can use: dnn-global-styles and dnn-webpack-externals. The first one pertains to styling, which we will discuss in a future blog. The second one - dnn-webpack-externals contains all the common React components made available in the Persona Bar.
An easy way to look at all the common components running is to open the developer tool in your browser with Persona Bar running and issue the following command:
dnn.nodeModules.CommonComponents
It will list all the common components, e.g. Button, Checkbox, etc.
Entry point in the App
Each app must have a starting point. We use Webpack as the module loader, where the starting point needs to be defined. In our example, it is indicated by entry. This points to main.jsx file under src sub-folder.
Main.jsx
The main.jsx file has a render method that contains Provider, Root and Container.
Provider pertains to Redux state, that we will discuss in a future blog. Use of Redux is optional, however we are using Redux heavily for state management, so might as well have it from the get go.
The Container points to the div on the Html file to which the React app will hook itself to. Root is where the real application starts.
Root.js
Root is defined under src/containers folder. It simply loads a production or development version of the application. We will talk about development tools in a future blog. They both load a component called App.
App.jsx
App is defined under src/components. This is where the application really starts. The common components are mostly used here or any other sub-components referenced further. In this example, we are using two common components – PersonaBarPage and SocialPanelHeader. PersonaBarPage has one property – isOpen. SocialPanelHeader also has one property – title. In this example we are setting the value of title as Hello World, which is what gets printed in the final Html output.
The properties exposed by these common components can also be seen in the developer console.
Final Html Markup
The final html mark shows the common components used in the app. It also shows the main div for the application – hello-world-container.