React – Extended boundary of Power Apps component framework
In previous post I demonstrated about how to use React with the former version of Power Apps component framework (PCF) by modifying PCF packages, which is unsupported.
Recently, the Microsoft PCF team finally announced their official support of React with PCF and released an example on how to achieve it. To my surprise, the approach I described in my previous blog post was conceptually similar to theirs.
I personally feel Microsoft’s example is too complex to understand to someone who is not familiar with React.
In this post I am going to explain how to use React in Power Apps component framework, through a step-by-step explanation, using a very basic component, a text box. This blog post is intended to those developers who are not familiar with React.
Skipping the basic steps, below are the 3 React principles you need to be familiar with
- Props – Props are immutable and therefore read-only. A component must never modify its own props.
- State – A state can be local or encapsulated. It is not accessible to any component other than the one that owns and sets it.
For example, you can create a component and assign it some props by the caller. The component will then manage its own state.
React is designed for “top-down” or “unidirectional” data flow.
A picture is worth a thousand words
Before we start, I would like to present the following diagram. It summarises the concept of using React in PCF.
PCF component will pass the Input value and a custom function (in this example, it is notifyChange) to React component via Props. In React component, we will copy Props into State in componentWillReceiveProps. Now, we can make changes to the State value in React component. When we decide to send the value from PCF, we will call the function notifyChange which will then signal its new value to PCF.
Based on this diagram, we are going to build a simple text box using React.
Build a simple text box without React
You can follow Microsoft documentation to create a PCF project. Once you open it in Visual Studio Code, let’s create a sample text box using TypeScript. You can find the sample code for this step here.
Principle #1 and creating a React component
To create a React component, let’s create a new file called ReactSampleTextBox.tsx, and add the code from here. In render() function, we are creating an input text.
Now, go back to index.ts and render the ReactSampleTextBox component. Code can be found here.
We will start to see the benefit of using React. Your index.ts becomes much cleaner. You will see an input text from React component when you run the component. Please note we are here to create a simple React component without passing any data from the PCF component.
Principle #2 and passing data
In PCF, this principle is about passing data from PCF to the custom React component. However, the principle states that we must use Props to pass the data to our custom React component and that it must remain read-only. But, since we have States, we use componentWillReceiveProps to set the value of Props to State.
Now, it’s time to modify index.ts and ReactSampleTextBox.tsx for passing data.
First, in ReactSampleTextBox.tsx, we need to declare an Interface for props. Let’s call it IProps and it has a property called value. We will use this value property to pass data from PCF to React component. Your ReactSampleTextBox.tsx will look like following. The value property of the input text is bound to props value of React component
In index.ts, declare an object props whose type is IProps from ReactSampleTextBox, assign the value in updateView and pass it to React component on rendering.
When you test the control, you will see the input text in React component will show any value you change via Inputs panel. However, you will NOT be able to directly edit any value in React text box. This is because we don’t tell the input text what to do. Let’s modify ReactSampleTextBox.tsx as following. Here, we create handleChange function, bind it in constructor and bind it onChange event of the input text.
First, let’s create IState interface. And copy the props value into the state in both constructor and componentWillReceiveProps. Next, we create handleChange function and bind it to the input text. Now, if you run the component, you will be able to pass value to React component from Inputs panel and you will be able to change value in text box.
You will notice any value change in React component text box will NOT show in Outputs panel.
Principle #3 and its problem
In the PCF example the third principle is about passing data from custom React component back to PCF. Since React is “unidirectional” how do we pass data from our React component back to PCF?
When using React for pages rendering purposes, a unidirectional data flow is not a problem. We tend to send data to the server-side using HTML Forms and re-render the page.
This could be troublesome with PCF as we have to use notifyOutputChanged in the init method to notify PowerApps Forms that the value has been changed in the component.
Getting around with the third principle issue
To get around this issue, we need to create a notifyChange function, which will update the output value of PCF and call the notifyOutputChanged in our PCF component.
We can pass the notifyChange function to our custom React component as part of props. Whenever a value is updated in our React component, the notifyChange function is executed, which will subsequently call notifyOutputChanged to update the output value and subsequently trigger onChange event on PowerApps Form.
Let’s make small changes to ReactSampleTextBox.tsx by adding onChange property in IProps. Now, when handleChange is executed, we will execute onChange function from props.
Now, back to index.ts. Create a new function called notifyChange which will then call notifyOutputChange.
The last thing to do is to pass notifyChange from index.ts to ReactSampleTextBox as props.
Run it to enjoy React component in PCF. The code can be found here.
I agree this type of component can be done without React. My intention, however, is to explain how values are passed between PCF and React component, and I believe building a very simple component is the best approach to explain the whole process.
If you are hard-core React developer, you might want to use redux to manage the state in a clean way. Field template component will unlikely require redux. However, if you are building a complex dataset component, not only for display but also for CRUD, redux is worth to check out.
Hopefully this post has been helpful to anyone beginning their adventure with React in PCF.