Building the NavigationMenu React Component for SPFx Top Placeholder
In the previous article we implemented a SharePoint Framework (SPFx) Application Customizer that injects a React component into the Top placeholder of the SharePoint page. Now, let’s dive into the core of this customization: the NavigationMenu component.
This component is responsible for rendering a menu based on configuration or list data passed via props.
Component Design
Expected Props
In the previous class, NavigationMenu was invoked as:
<NavigationMenu
type="Default"
ListTitle="TopMenu"
AppContext={this.context}
siteUrl="https://sharepoint.com/sites/site"
/>
This suggests the component is dynamic and context-aware, receiving:
type: A string to determine menu style or variantListTitle: The SharePoint list that contains menu itemsAppContext: The current SPFx context, includingspHttpClient, page context, etc.siteUrl: The full URL of the target site where the list is located
Example Implementation of NavigationMenu.tsx
Here’s a possible technical implementation of NavigationMenu:
import * as React from 'react';
import { useEffect, useState } from 'react';
import { IContextInfo } from './types';
import { SPHttpClient } from '@microsoft/sp-http';
export interface INavigationMenuProps {
type: string;
ListTitle: string;
AppContext: IContextInfo;
siteUrl: string;
}
interface IMenuItem {
Title: string;
Url: string;
}
const NavigationMenu: React.FC<INavigationMenuProps> = (props) => {
const [items, setItems] = useState<IMenuItem[]>([]);
useEffect(() => {
loadMenuItems();
}, []);
const loadMenuItems = async () => {
const endpoint = `${props.siteUrl}/_api/web/lists/getbytitle('${props.ListTitle}')/items?$select=Title,Url`;
const response = await props.AppContext.spHttpClient.get(endpoint, SPHttpClient.configurations.v1);
if (response.ok) {
const json = await response.json();
setItems(json.value);
} else {
console.error("Failed to fetch menu items");
}
};
return (
<nav className={`custom-menu custom-menu-${props.type}`}>
<ul>
{items.map((item, index) => (
<li key={index}><a href={item.Url}>{item.Title}</a></li>
))}
</ul>
</nav>
);
};
export default NavigationMenu;
Technical Breakdown
| Element | Description |
|---|---|
useEffect() | Fetches menu items once the component is mounted |
SPHttpClient | Provided by AppContext, used to call SharePoint REST API |
ListTitle | Identifies which list to pull data from |
siteUrl | Base site to construct the API call |
setItems() | Updates React state with menu entries |
custom-menu-${props.type} | Enables dynamic theming via CSS classes |
Expected SharePoint List Structure
For this menu to work correctly, the SharePoint list named TopMenu should have at least the following columns:
| Column Name | Internal Name | Type |
|---|---|---|
| Title | Title | Text |
| Url | Url | Hyperlink or Text |
These columns are referenced in the REST API call:/_api/web/lists/getbytitle('TopMenu')/items?$select=Title,Url
Styling the Menu
Basic CSS structure (can be extended for themes or variants):
.custom-menu {
background-color: #f3f3f3;
padding: 10px;
}
.custom-menu ul {
list-style-type: none;
margin: 0;
padding: 0;
display: flex;
gap: 15px;
}
.custom-menu li a {
text-decoration: none;
font-weight: bold;
color: #0078d4;
}
Summary Table
| Feature | Description |
|---|---|
NavigationMenu | React component rendering menu links |
AppContext.spHttpClient | Used to query the SharePoint list |
siteUrl | Allows querying across site collections |
ListTitle | Identifies which SharePoint list to use |
type | Optional styling flag |
IMenuItem interface | Defines the structure of each menu item |
| REST API Used | /_api/web/lists/getbytitle('List')/items?$select=Title,Url |
