microsoft-graph-toolkit icon indicating copy to clipboard operation
microsoft-graph-toolkit copied to clipboard

When using <PeoplePicker selectionMode={'multiple'} selectedPeople={Array of emails} I get no name and picture and error

Open Ofer-Gal opened this issue 2 years ago • 16 comments

Describe the bug My code is

                       <PeoplePicker placeholder={'Up to 50 people'} selectionMode={'multiple'}
                            id="AdditionalRecipients" disabled={!dpcRequest.LockedToMe}
                            selectedPeople={graphIds}//defaultSelectedUserIds={graphIds} //
                            showMax={50}
                            selectionChanged={onAdditionalRecipientsChanged}
                        />

To Reproduce populate graphIds with array of emails 4. See error

Uncaught TypeError TypeError: Cannot use 'in' operator to search for 'groupTypes' in [email protected]
    at n (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:553:541)
    at <anonymous> (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:553:1964)
    at loadState (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:553:1706)
    at <anonymous> (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:982:13919)
    at <anonymous> (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:982:11789)
    at c (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:982:11537)
    at <anonymous> (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:982:13805)
    at <anonymous> (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:982:13786)
    at <anonymous> (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:982:11789)
    at c (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:982:11537)
    at requestStateUpdate (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:982:13513)
    at firstUpdated (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:982:13176)
    at performUpdate (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:889:18131)
    at _enqueueUpdate (C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:889:17642)
n @ C:\Users\ogal\source\repos\SPFx\SPFx14\DPCOneJobScreen\node_modules\@microsoft\mgt-spfx\dist\mgt-library_ec012d888c08087c4879.js:553:541

Expected behavior Show user picture and name in people picker

Screenshots Shows image

Environment (please complete the following information):

  • OS: [windows]
  • Browser [chrome]
  • Framework [react ]
  • Context [SharePoint]
  • Version [e.g. 2.4]
  • Provider [ spfx

when using array of graph IDs nothing shows

Ofer-Gal avatar Apr 06 '22 19:04 Ofer-Gal

Hello Ofer-Gal, thank you for opening an issue with us!

I have automatically added a "needs triage" label to help get things started. Our team will analyze and investigate the issue, and escalate it to the relevant team if possible. Other community members may also look into the issue and provide feedback 🙌

ghost avatar Apr 06 '22 19:04 ghost

I just replied to your question, can you validate this is an array and not an enumerable or collection? If you use Array.from(), does it work?

sebastienlevert avatar May 09 '22 17:05 sebastienlevert

graphIds is a state variable which is an array. How would I use Array.from()?

Array.from(graphIds); ?

I will try later.

Ofer-Gal avatar May 09 '22 23:05 Ofer-Gal

Exactly!

sebastienlevert avatar May 10 '22 14:05 sebastienlevert

Now with version following the doc defaultSelectedUserIds expects a string "a string of comma-separated Microsoft Graph user IDs" so when I set a state variable as string. Typescript complaines that defaultSelectedUserIds should be a string array Important to mention this is React!

import { PeoplePicker } from '@microsoft/mgt-react/dist/es6/spfx';

later

                    <PeoplePicker placeholder={'Up to 50 people'} selectionMode={'multiple'} 
                            id="AdditionalRecipients" disabled={!dpcRequest.LockedToMe}
                            defaultSelectedUserIds={[graphIds]} // {graphIds}  is an error                            // selectedPeople={graphIds}
                            showMax={50}
                            selectionChanged={onAdditionalRecipientsChanged}
                        />

Can I get a working example where the defaultSelectedUserIds or selectedPeople is populate from a state variable and not hard coded?

Thank you

I also started seeing the following in the console:

Uncaught DOMException DOMException: Failed to execute 'get' on 'IDBObjectStore': No key or key range specified.

anything I can do about it?

Ofer-Gal avatar Jul 13 '22 08:07 Ofer-Gal

Just to confirm. Your array of graphIds is an array of ['GUID', 'GUID', ...]?

sebastienlevert avatar Jul 19 '22 18:07 sebastienlevert

Yes it is

Ofer-Gal avatar Jul 20 '22 05:07 Ofer-Gal

With this repro, I can't get your issues... Is there anything that impacts it?

https://stackblitz.com/edit/mgt-1644?file=App.tsx

sebastienlevert avatar Jul 20 '22 14:07 sebastienlevert

Guess the only difference is that my implementation is in a SPFx webpart and real 365 tenant rather than "MockProvider" My provider init in the ...webpart.ts is:

    if (!Providers.globalProvider) {
      Providers.globalProvider = new SharePointProvider(this.context);
    }

Actually, I managed to change it and show the issue on the forked https://stackblitz.com/edit/mgt-1644-khlofu?file=App.tsx See how when the array is created on the " React.useEffect" and saved into state variable "startPeople" to do it like in the code that calls SharePoint and Graph to get the users, then when using the startPeople for defaultSelectedUserIds the users do not show

See if you can fix it :-) Thanks for the help

Ofer-Gal avatar Jul 20 '22 15:07 Ofer-Gal

Now I understand your point. And this feels like a nasty React + MGT bug. @musale / @gavinbarron / @Mnickii anybody can confirm the bug and how this doesn't work with the useEffect on the initial load? When following through the callstack I see the defaultSelectedUserIds being empty, then nothing... It feels like the DOM doesn't reload when useEffect is hit. Is it a misuse of the useEffect or MGT doesn't trigger?

sebastienlevert avatar Jul 20 '22 17:07 sebastienlevert

Interesting. This seems to be a conflation of defaultSelectedUserIds and selectedUsers. Based on my experimentation defaultSelectedUserIds is only used during initialization.

Compare these two behaviors: Defer loading until default list populated - defaultSelectedUserIds Load immediately - update the value bound to selectedPeople

It feels like this behavior is by design to me @Ofer-Gal does this resolve your issue? If not, can you give us a bit more detail around your scenario?

gavinbarron avatar Jul 21 '22 03:07 gavinbarron

Both have the await sleep(5000); and both seem to fix at first. when I I clicked Load immediately - update the value bound to selectedPeople a second time, I see just icons. image

I will try the first method in the web part later.

Thanks for the help

Ofer-Gal avatar Jul 21 '22 12:07 Ofer-Gal

Yeah, the selectedPeople option expects an array of person type objects, not just an array of ids, so I made a shameless hack in the interests of showing the functionality, note how the array contains objects with the id property set.

@Ofer-Gal I'm going to mark this as closed now, please feel free to re-open if you need to.

gavinbarron avatar Jul 21 '22 14:07 gavinbarron

In my SPFx Web Part (now MGT 2.6.0) it only show correctly when using literals like in the Demo.

defaultSelectedUserIds={['67bfd792-fe22-477c-9b11-4c1c63237b4e','d661d903-3fd0-496e-a356-cb96ecd10e60','[email protected]']} 

When using variables

const [graphIds, setGraphIds] = React.useState(null);

const others:string[] ="'67bfd792-fe22-477c-9b11-4c1c63237b4e','d661d903-3fd0-496e-a356-	 
    cb96ecd10e60','[email protected]'".split(",");
setGraphIds(others)

then in the component

defaultSelectedUserIds={graphIds} 

It shows nothing.

Do you want to leave it only good for demos? :-) Actual usage will always involve using variables, and with multi, it will always be an array .

Thanks any way

Ofer-Gal avatar Jul 22 '22 04:07 Ofer-Gal

Interestingly enough, this works using our Web Component, but it has a hard time with React, probably because of the way it seems to only support initialization. @gavinbarron what if we reopen this and look in details later? This seems like a valid scenario as I would say devs should not hardcode user ids in their code 😎

sebastienlevert avatar Jul 22 '22 16:07 sebastienlevert

@Ofer-Gal thank you for calling out this challenge. This has to be addressed. We can't ship code that isn't useful in production scenarios as you rightly point out.

@sebastienlevert yes, this is a real-world issue and we need to resolve it.

gavinbarron avatar Jul 22 '22 17:07 gavinbarron

Hello @sebastienlevert is this fix going to be in Milestone 2022-12 and if so, do you have an estimate on when this will be released? Many thanks

pwmather avatar Jan 18 '23 17:01 pwmather

@pwmather This was not delivered in the 2022-12 milestone and has been reprioritized to be part of the v3.0.0 milestone. We expect to be in a preview state for v3.0.0 by the end of February 2023

gavinbarron avatar Jan 31 '23 18:01 gavinbarron

Thank you for the update @gavinbarron

pwmather avatar Jan 31 '23 18:01 pwmather

Oh my gosh, I'm sorry I missed this earlier.

The react code here doesn't work because the defaultSelectedUserIds is not set on the initial render.

const [graphIds, setGraphIds] = React.useState(null);

const others:string[] ="'67bfd792-fe22-477c-9b11-4c1c63237b4e','d661d903-3fd0-496e-a356-	 
cb96ecd10e60','[email protected]'".split(",");

setGraphIds(others);

return (<PeoplePicker placeholder={'Up to 50 people'} selectionMode={'multiple'} 
                            id="AdditionalRecipients" disabled={!dpcRequest.LockedToMe}
                            defaultSelectedUserIds={graphIds}
                            showMax={50}
                            selectionChanged={onAdditionalRecipientsChanged}
                        />

What's happening is that the state of graphIds is null on the initial render. The call to setGraphIds(others) updates the value of graphIds after the first render of the component and enqueues another render, the React docs are not very good at noting this subtle behavior IMO and it's a super easy mistake to make, https://reactjs.org/docs/hooks-reference.html#usestate

I would avoid rendering the PeoplePicker until after there is content in the graphIds array to be passed as the default value. Seb has made a helpful demo on stack blitz showing this behavior: https://stackblitz.com/edit/mgt-1644-dsej75?file=App.tsx

Now, there's a legitimate bug here in that when updating the value of defaultSelectedUserIds doesn't trigger an update to the state of the component and a fetch to graph and the code as above will correctly render the selected users after a user gives focus to the input box, which does trigger the state update using the updated set of defaultSelectedUserIds

gavinbarron avatar Feb 06 '23 20:02 gavinbarron

Thanks. I will try this.

Ofer-Gal avatar Feb 07 '23 07:02 Ofer-Gal

Works Thx

Ofer-Gal avatar Feb 11 '23 06:02 Ofer-Gal