Skip to main content

Notifications

Community site session details

Community site session details

Session Id :
Power Apps - Power Apps Pro Dev & ISV
Answered

Change in PCF Controls load null data on initial load

(0) ShareShare
ReportReport
Posted on by 41

Recently a control I have had published for quiet some time started to break (in July). This code base has not changed and has been working fine for some time. Trying to determine what update is causing this change in behavior. The issue is on initial load the field mapped to the control shows null data. But if you do a post back again (F5) it will work on the second load and if you exit the record and re-open it will work fine. Trying to understand why all of a sudden it's displaying null on initial load. As I have said - the code hasn't changed since Mar 18, 2020.  This is a modified version of the PeoplePicker control -

 

import { IInputs, IOutputs } from "./generated/ManifestTypes";
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { PeoplePickerTypes, IPeopleProps, IPeoplePersona } from './Peoplepicker';

export class OfficeUIFabricReactPeoplePicker implements ComponentFramework.StandardControl<IInputs, IOutputs> {
	private theContainer: HTMLDivElement;
	private notifyOutputChanged: () => void;
	private _context: ComponentFramework.Context<IInputs>;
	private props: IPeopleProps = {
		//tableValue: this.numberFacesChanged.bind(this),
		peopleList: this.peopleList.bind(this),
	}

	/**
	 * Empty constructor.
	 */
	constructor() {

	}

	/**
	 * Used to initialize the control instance. Controls can kick off remote server calls and other initialization actions here.
	 * Data-set values are not initialized here, use updateView.
	 * @Param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to property names defined in the manifest, as well as utility functions.
	 * @Param notifyOutputChanged A callback method to alert the framework that the control has new outputs ready to be retrieved asynchronously.
	 * @Param state A piece of data that persists in one session for a single user. Can be set at any point in a controls life cycle by calling 'setControlState' in the Mode interface.
	 * @Param container If a control is marked control-type='standard', it will receive an empty div element within which it can render its content.
	 */
	public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container: HTMLDivElement) {
		// Add control initialization code
		this.notifyOutputChanged = notifyOutputChanged;
		this._context = context;
		this.theContainer = container;
	}


	/**
	 * Called when any value in the property bag has changed. This includes field values, data-sets, global values such as container height and width, offline status, control metadata values such as label, visible, etc.
	 * @Param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to names defined in the manifest, as well as utility functions
	 */
	public async updateView(context: ComponentFramework.Context<IInputs>) {
		// Add code to update control view
		this.props.context = context;
		if (context.parameters.peoplePicker.raw !== null) {
			if (context.parameters.peoplePicker.raw!.indexOf("text") > 1) {
				this.props.preselectedpeople = JSON.parse(context.parameters.peoplePicker.raw!);
			}
		}

		ReactDOM.render(
			React.createElement(
				PeoplePickerTypes,
				this.props
			),
			this.theContainer
		);

	}

	/** 
	 * It is called by the framework prior to a control receiving new data. 
	 * @returns an object based on nomenclature defined in manifest, expecting object[s] for property marked as “bound” or “output”
	 */
	public getOutputs(): IOutputs {
		return {
			peoplePicker: JSON.stringify(this.props.people)
		};
	}

	private peopleList(newValue: IPeoplePersona[]) {
		if (this.props.people !== newValue) {
			if (newValue.length === 0) {
				this.props.people = undefined;
			}
			else {
				this.props.people = newValue;
			}

			this.notifyOutputChanged();
		}
	}

	/** 
	 * Called when the control is to be removed from the DOM tree. Controls should use this call for cleanup.
	 * i.e. cancelling any pending remote calls, removing listeners, etc.
	 */
	public destroy(): void {
		// Add code to cleanup control if necessary
		ReactDOM.unmountComponentAtNode(this.theContainer);
	}
}

 

  • Diana Birkelbach Profile Picture
    3,072 Most Valuable Professional on at
    Re: Change in PCF Controls load null data on initial load

    Hi @shadowfox , Hi @cchannon , 


    I think my explanation was not clear. What I was trying to say:


    Looking at your code, I see that the this.props are still passed to the react component. This is the code you used:

    public async updateView(context: ComponentFramework.Context<IInputs>) {
    		// Add code to update control view
    		this.props.context = context;
    		if (context.parameters.peoplePicker.raw !== null) {
    			if (context.parameters.peoplePicker.raw!.indexOf("text") > 1) {
    				this.props.preselectedpeople = JSON.parse(context.parameters.peoplePicker.raw!);
    			}
    		}
    
    		ReactDOM.render(
    			React.createElement(
    				PeoplePickerTypes,
    				this.props
    			),
    			this.theContainer
    		);
    
    	}

    The point is: the this.props are passed to the PeoplePickerTypes as props. But this.props is a reference that never changes. Only the content inside the this.props changes, but for react it is a pointer that never changes. React doesn't detect the change, and that's why the second time when updateView is called, React won't render again, so only the null value is shown, even if the render is called again.. 

    Unmounting will cost unnecessary time, so before you give up, I would try something like this (consider a local object):

    //using a local myProps instead of this.props
    public updateView(context: ComponentFramework.Context<IInputs>) {
    	// Add code to update control view
    	const myProps={ ....} //only the props you need
    
    	ReactDOM.render(
    		React.createElement(
    			PeoplePickerTypes,
    			myProps
    		),
    		this.theContainer
    	);
    
    }

    Or, if you want to keep the this.props, you can use as "...this.props"; this way you pass a new object as  props to your react component, with exactly the same content.

    public updateView(context: ComponentFramework.Context<IInputs>) {
    	//.. the same as you have, but render with ...this.props
    	ReactDOM.render(
    		React.createElement(
    			PeoplePickerTypes,
    			...this.props
    		),
    		this.theContainer
    	);
    
    }

     

    Hope this helps!

     

    Kind regards,

    Diana

     

    PS: @cchannon Thanks for looking at me as a react dev :-). 

  • shadowfox Profile Picture
    41 on at
    Re: Change in PCF Controls load null data on initial load

    And @cchannon I agree - according to React documentation - you should not have to do this for rendering. By calling it a second time - it should simply update the current version of the control but was not doing that. 

  • shadowfox Profile Picture
    41 on at
    Re: Change in PCF Controls load null data on initial load

    @cchannon that did the trick. Thanks for the help! Wish I knew why the change in behavior though. 

  • cchannon Profile Picture
    4,702 Super User 2025 Season 1 on at
    Re: Change in PCF Controls load null data on initial load

    ...Oh, and a quick note for the react devs (looking at you, @DianaBirkelbach!) who will see this and tell me unmountComponentAtNode should be unnecessary and the component should properly handle updated props: yes, you're correct, but this seems like the more expedient resolution for this forum post.

  • shadowfox Profile Picture
    41 on at
    Re: Change in PCF Controls load null data on initial load

    @cchannon thanks - I'll try this to see if it fixes it. Glad to hear you've seen the null first, value second thing. I thought I had as well - but honestly I couldn't remember with this control - so didn't want to guess. What's bugging me is that the control was working and then broke.... That's what's causing me the most worry. Whatever did this - is it going to break my other stuff? Thanks again for all the help.

  • cchannon Profile Picture
    4,702 Super User 2025 Season 1 on at
    Re: Change in PCF Controls load null data on initial load

    Oh, and of course, in your ./Peoplepicker.tsx you need to make sure you can safely handle a null so it doesn't throw exceptions either.

  • Verified answer
    cchannon Profile Picture
    4,702 Super User 2025 Season 1 on at
    Re: Change in PCF Controls load null data on initial load

    No, the "null first, value second" thing is something I've seen before, that's why I knew to guess it. I am not sure how to reliably reproduce (or avoid) it, which is why I just take approaches that circumvent it. So again, make sure your nullcheck is safe (you already have a !== null, so that should safely avoid any exceptions) then add in a line right before your reactdom.render, basically the same thing you are doing in Dispose:

     

    ReactDOM.unmountComponentAtNode(this.theContainer);

     

    This will let your component run once, with a null string, which will render nothing in the picker. But then when updateView gets called again and has a value, it will unload that empty version of the control and reload with an actual value.

  • shadowfox Profile Picture
    41 on at
    Re: Change in PCF Controls load null data on initial load

    @cchannon correct - it gets called twice on cold load. First time null, second time it has data (that's what I was trying to show in the images above - hope it made sense). However - due to it being null on initial load - it's breaking it for some reason. When the record is closed and reopen - both times the updateview is called - it has data (first call and then second call) - that's the only difference. And in that case it renders. 

    Sadly - I can't test what it use to do to see if it use to be null on the cold open first call like it is now since this is occurring in our dev, test, and prod environments. So not sure if that has changed or not. Thanks for the help - this has me stumped. 

    I'm really leaning towards - something rendering controls has changed since this worked completely fine and just started to act up recently and code hasn't changed on index at all. 

  • cchannon Profile Picture
    4,702 Super User 2025 Season 1 on at
    Re: Change in PCF Controls load null data on initial load

    ... IF it starts as null, then in later updates actually gives you the value, then what you want is to render your control on the last updateView. So maybe try just sticking in a unloadcomponentatnode right before your reactdom.render. That way you are sure that every time this runs it wipes out the old one and renders anew. This will guarantee you that whatever you get on the last updateView is what the user will see.

  • cchannon Profile Picture
    4,702 Super User 2025 Season 1 on at
    Re: Change in PCF Controls load null data on initial load

    Well, updateView gets called multiple times onLoad (at least two, could be more depending on what's happening on your form) and you can even force it to fire with Client Script by using the fireOnChange() function.

     

    So try debugging again and just put your breakpoint at the top of updateView. Is contex.parameters.peoplePicker null every time updateView gets called, or maybe just the first time?

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

🌸 Community Spring Festival 2025 Challenge Winners! 🌸

Congratulations to all our community participants!

Warren Belz – Community Spotlight

We are honored to recognize Warren Belz as our May 2025 Community…

Congratulations to the April Top 10 Community Stars!

Thanks for all your good work in the Community!

Leaderboard > Power Apps - Power Apps Pro Dev & ISV

#1
WarrenBelz Profile Picture

WarrenBelz 85 Most Valuable Professional

#2
Michael E. Gernaey Profile Picture

Michael E. Gernaey 65 Super User 2025 Season 1

#3
mmbr1606 Profile Picture

mmbr1606 55 Super User 2025 Season 1

Overall leaderboard