The Pros and Cons of Fluent UI React

I recently got to know Fluent UI React when I used it in custom SPFx webpart. Fluent UI React is a framework of customizable components from Microsoft that fit seemlessly into Microsoft products like SharePoint. If you aren’t familiar with Fluent UI, don’t feel bad. It is the relatively new rebranded Office Fabric React. Ahh, you gotta love how Microsoft is always renaming things! Just when we get used to saying something, they decide to change it. So whether you know it as Office Fabric or Fluent UI, here is my take on working with it.

The things I like:

  • The variety of components from which to choose
    • There are basic inputs, pickers, lists, menus, surfaces, notifications and much more
  • For the most part, how relatively simple it is to import a component and get it working and looking great
  • The default styling that doesn’t require any code
  • The ability to customize the look and functionality of the components
  • Using CSS-in-JS
    • I have to be honest, I didn’t think I would like this. It is not how I learned to code, it bulks up your file, and it can be confusing at first. However, I love the idea of CSS that just belongs to my component. It doesn’t fight with other CSS and I don’t have to hunt for code affecting my component.

The things I don’t like:

  • The documentation is seriously lacking!!! I mean, it really isn’t good people.
    • I spent so many hours banging my head against the wall simply because things aren’t documented well.
    • Some will argue and say that the documentation includes sample code. Yeah, except many of the samples pull in hidden code or are missing critical pieces.
  • The inconsistency of the properties that are available on the components.
    • For example, not all inputs have error handling and/or validation properties.
  • The more complex components can be difficult to figure out, especially since the documentation is so awful.
    • For example, figuring out how to get the PeoplePicker to work in conjunction with a Microsoft Graph call nearly ended me.
  • Customizing the look of some of the components is pretty tricky as well, and again the documentation is no help.
    • For example, try to change the background color of the checkbox so that it matches the background color of the app.

Regardless of the cons, I would still recommend checking out Fluent UI and trying it in your next Microsoft 365 project. It can be frustrating at times, but I would still say the pros outweigh the cons.

How to Save a MultiPerson PeoplePicker to a SharePoint List

In a recent project where I was building a SPFx webpart using React Hooks, Typescript, Fluent UI and PNPjs, I found myself struggling to save a multiperson peoplepicker to a SharePoint list. The biggest difficulty I was having was the fact that I needed to make a call to ensureUser to retrieve a user id for each person selected in the peoplepicker before I could save the group of users to the SharePoint list.

The ensureUser calls are async calls, which adds another layer of difficulty to this dilemma. At first glance, you might think, just loop through the users and make the call to ensureUser. Sure, that seems logical, except that leaves no way to wait for all of the calls to complete before moving on. In fact, when attempting this, I always ended up with an empty array in my peoplepicker, because the browser started each ensureUser call and immediately went on to saving the data before any of the ensureUser calls ever completed.

What I needed was a way to make multiple async calls and wait for all of them to be complete before I could move on to saving that data. Enter Promise.all, my prince riding in on a white horse! Promise.all is a promise that takes an array of promises and resolves when all of the promises have resolved or rejects when one of the promises is rejected. Sounds magical, doesn’t it?! Let’s see it in action:

const saveListItem = async => {
    let userIds = [];
    await Promise.all(selectedProject.ProjectTeam.map(async (member) => {
        let userId = await sp.web.ensureUser(`​${member.secondaryText}`);
            userIds.push(userId.data.Id);
    }));
    let projectTeamId = {
        ‘results’: userIds,
    };
    sp.web.lists.getByTitle(‘SharePointList’).items.getById(selectedProjectId).update({
        Status: selectedProject.Status,
        ProjectTeamId: projectTeamId,
    });
};

So what is happening here? I have created a function called saveListItem. It is important to note that this is an async function and you will need to use await when calling this function if you need to wait for it to resolve before moving on to whatever you are doing after it. It would look like this:


await saveListItem();

Inside the saveListItem function, you will see the magical Promise.all. I’m using await as I want to wait for Promise.all to resolve before moving on the the next bit of code. Promise.all is passed an array (selectedProject.ProjectTeam) of users. I map over the array and call ensureUser for each user to retrieve the userId. The result of the ensureUser call is then pushed to the userIds array.

Once all of the ensureUser calls have resolved, then the Promise.all resolves. The userIds array can then be used in the projectTeamId array, which will then be used to update the peoplepicker of the item in the SharePoint list.

To read more about Promise.all, check out the MDN web docs or this great blog: All you need to know about Promise.all.

 

Optional Chaining in JavaScript

Optional chaining is in stage 1 and can be found in this repo. Optional Chaining provides a succinct way to check for the existence of an object before accessing its properties.  2_bgVery similar to the C# null conditional operator. And it is already available in the React ecosystem.

Why do we need this?

How often are we checking for existence of an object after an API call? Yes, almost always requiring us to write code like this to prevent errors due to JavaScript’s nature of allowing unstructured anonymous objects. Continue reading “Optional Chaining in JavaScript”