I thought I’d give the latest version of SharePoint Framework a go, using the Yeoman generator to start an SPFx Application Customizer.
The documentation from Microsoft no longer has an opinion on which client-side framework to use for UI components. I still like React, it’s my go to framework because of its ubiquity, and flexibility.
When you follow Microsoft’s documentation Build your first application customizer extension, you end up with an SPFx project that doesn’t explicitly use a version of React, however, some of the SPFx libraries have React dependencies. As you can see in the output of npm ls react
, the following @microsoft
libraries continue to maintain a dependency on react:
- @microsoft/sp-application-base
- @microsoft/sp-core-library
As of today, adding react to your solution executing the command npm i react --save
adds a reference to React v17.0.2 (react@17.0.2
and react-dom@17.0.2
).
mark@Marks-2023-MacBook-Pro my-application-customizer % npm ls react
my-application-customizer@0.0.1 /Users/mark/Documents/Code/git/my-application-customizer
├─┬ @microsoft/sp-application-base@1.17.3
│ ├─┬ @microsoft/sp-component-base@1.17.3
│ │ └─┬ @fluentui/react@8.110.2
│ │ ├─┬ @fluentui/foundation-legacy@8.2.41
│ │ │ └── react@17.0.2 deduped
│ │ ├─┬ @fluentui/react-focus@8.8.28
│ │ │ └── react@17.0.2 deduped
│ │ ├─┬ @fluentui/react-hooks@8.6.27
│ │ │ └── react@17.0.2 deduped
│ │ ├─┬ @fluentui/react-portal-compat-context@9.0.6
│ │ │ └── react@17.0.2 deduped
│ │ ├─┬ @fluentui/react-window-provider@2.2.15
│ │ │ └── react@17.0.2 deduped
│ │ ├─┬ @fluentui/theme@2.6.32
│ │ │ └── react@17.0.2 deduped
│ │ ├─┬ @fluentui/utilities@8.13.16
│ │ │ └── react@17.0.2 deduped
│ │ └── react@17.0.2 deduped
│ └─┬ @microsoft/sp-loader@1.17.3
│ ├─┬ react-dom@17.0.1
│ │ └── react@17.0.1 deduped
│ └── react@17.0.1
├─┬ @microsoft/sp-core-library@1.17.3
│ └── react@17.0.2 deduped
├─┬ react-dom@17.0.2
│ └── react@17.0.2 deduped
└── react@17.0.2
When deploying this app to my dev tenant’s app catalog, or running it with the loadSPFX
query string, encounters the following errors in Dev tools / console:
Could not load my-application-customizer in require. TypeError: Cannot read properties of undefined (reading 'id')
The expanded error looks like this:
sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70 Could not load my-application-customizer in require. TypeError: Cannot read properties of undefined (reading 'id')
at sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70:750963
at new Promise (<anonymous>)
at e.loadComponent (sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70:750931)
at sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70:752692
at async Promise.all (/sites/index 0)
(anonymous) @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
Promise.catch (async)
e._loadComponent @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
(anonymous) @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
Promise.catch (async)
e._loadComponent @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
(anonymous) @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
Promise.catch (async)
e._loadComponent @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
e.loadComponent @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
(anonymous) @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
e.loadComponent @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
e.loadComponent @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
e.loadComponent @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
e.createExtension @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
e._createApplicationCustomizer @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
e._loadExtensions @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
e.loadExtensions @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
e._loadApplicationCustomizers @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
(anonymous) @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
Promise.then (async)
e.navigate @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
e.navigateToApplication @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
c @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
(anonymous) @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
s @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
e._startApplication @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
e._startApplication @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
(anonymous) @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
Promise.then (async)
e.start @ sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70
(anonymous) @ CommunicationSite20230612?debugManifestsFile=https%3A%2F%2Flocalhost%3A4321%2Ftemp%2Fmanifests.js&loadSPFX=true&customActions=%7B%2205c4cd67-280e-41e1-bec3-d037cfce6e7e%22%3A%7B%22location%22%3A%22ClientSideExtension.ApplicationCustomizer%22%2C%22properties%22%3A%7B%22testMessage%22%3A%22Test+message%22%7D%7D%7D:74
(anonymous) @ CommunicationSite20230612?debugManifestsFile=https%3A%2F%2Flocalhost%3A4321%2Ftemp%2Fmanifests.js&loadSPFX=true&customActions=%7B%2205c4cd67-280e-41e1-bec3-d037cfce6e7e%22%3A%7B%22location%22%3A%22ClientSideExtension.ApplicationCustomizer%22%2C%22properties%22%3A%7B%22testMessage%22%3A%22Test+message%22%7D%7D%7D:74
sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70 Uncaught (in promise) Error: Failed to create application customizer 'ClientSideExtension.ApplicationCustomizer.05c4cd67-280e-41e1-bec3-d037cfce6e7e'. Error information is 'Extension failed to load for componentId "05c4cd67-280e-41e1-bec3-d037cfce6e7e".'.
at sp-pages-assembly_en-us_e8c337923cf862c9440d3af26fb9d655.js:70:1471072
at async Promise.all (/sites/index 0)
I found the solution to this is to override the latest version of react
and react-dom
(v17.0.2) with one patch release prior v17.0.1. The easiest way to do this is to execute the following command:
mark@Marks-2023-MacBook-Pro my-application-customizer % npm i react@17.0.1 react-dom@17.0.1 --save
After downgrading to v17.0.1, the following output is shown when executing npm ls react
:
mark@Marks-2023-MacBook-Pro my-application-customizer % npm ls react
my-application-customizer@0.0.1 /Users/mark/Documents/Code/git/my-application-customizer
├─┬ @microsoft/sp-application-base@1.17.3
│ ├─┬ @microsoft/sp-component-base@1.17.3
│ │ └─┬ @fluentui/react@8.110.2
│ │ ├─┬ @fluentui/foundation-legacy@8.2.41
│ │ │ └── react@17.0.1 deduped
│ │ ├─┬ @fluentui/react-focus@8.8.28
│ │ │ └── react@17.0.1 deduped
│ │ ├─┬ @fluentui/react-hooks@8.6.27
│ │ │ └── react@17.0.1 deduped
│ │ ├─┬ @fluentui/react-portal-compat-context@9.0.6
│ │ │ └── react@17.0.1 deduped
│ │ ├─┬ @fluentui/react-window-provider@2.2.15
│ │ │ └── react@17.0.1 deduped
│ │ ├─┬ @fluentui/theme@2.6.32
│ │ │ └── react@17.0.1 deduped
│ │ ├─┬ @fluentui/utilities@8.13.16
│ │ │ └── react@17.0.1 deduped
│ │ └── react@17.0.1 deduped
│ └─┬ @microsoft/sp-loader@1.17.3
│ └── react@17.0.1 deduped
├─┬ @microsoft/sp-core-library@1.17.3
│ └── react@17.0.1 deduped
├─┬ react-dom@17.0.1
│ └── react@17.0.1 deduped
└── react@17.0.1
Note, all version references to react
and react-dom
now refer to 17.0.1. Start the debug build of your project again with gulp serve --nobrowser
, refresh your browser window, and your React components will start rendering as expected.
Supporting documentation and resources
The following page published by Microsoft describes compatibility of Node, NPM, TypeScript, and React for different versions of SPFx. When starting a new SPFx project where you’re using React, you should check this page to confirm which version of React to install:
This is acknowledged by the wonderful M365 PnP community in the following GitHub issue:
And also appears to be similar to a number of issues on Stack Overflow: