Consume Lookup Multi Select Fields SPFx with Models and Hooks

Pexels Sora Shimazaki 5926380
Photo by Sora Shimazaki

First when you set up lookup columns in a list or library, Microsoft restricts you to 12 columns of that type in a single view. The reason behind this limitation is that lookup columns retrieve data from another list or source. If you surpass this limit and try to add a 13th column, you’ll encounter an error message. It seems that 13 isn’t a lucky number in this case!

But if for your use case makes sense, here it is a solutions using the SharePoint Framework SPFx, not to bypass but use.

See my previous posts about Models and Hooks

Use Models

/* Model to MAP */
export interface IMyModelToMap {
    MyId: number;
    MyText: string;
    MyMultiSelectLookup: IMylMultiSelectResponse[];

/* IMyMainResponse Response */
export interface IMyMainResponse {
    Id: number;
    Title: string;
    MyMultiSelectLookup: IMylMultiSelectResponse[];

/* IMylMultiSelectResponse Response */
export interface IMylMultiSelectResponse {
    Id: number;
    Title: string;

Your Custom Hook

import { Logger, LogLevel } from "@pnp/logging";
import { spfi, SPFI } from "@pnp/sp";
import { useEffect, useState } from "react";
// Interfaces
import { IMyMainResponse, IMyModelToMap } from "../interfaces/MyModel"
import { getSP } from "../pnpjsConfig";
import { Caching } from "@pnp/queryable";

const useTranings = () => {

    const LOG_SOURCE = "PnPLog";
    const LIBRARY_NAME = "Your List Name"

    const [myItems, setMyItems] = useState<IMyModelToMap[]>([]);
    const [isError, setError] = useState<boolean>(false);

    const _sp: SPFI = getSP();
        //Side Effect
        useEffect(() => {
            (async () => {
                try {
                    const spCache = spfi(_sp).using(Caching({ store: "session" }))
                    const response: IMyMainResponse[] = await spCache.web.lists

                        const items: IMyModelToMap[] = IMyMainResponse) => {
                            return {
                             MyId: item.Id || 0,
                             MyText: item.Title || "undefined",
                             MyMultiSelectLookup: item.MyMultiSelectLookup || []

                } catch (err) {
                        `${LOG_SOURCE} (getting files useEffect setMyItems) - ${JSON.stringify(err)} - `, LogLevel.Error
        }, []);

        return [myItems, isError] as const

export default useYourCustomHook

Our React Control

//* Omitted for abbreviation */

//Custom Hook
import useYourCustomHook from '../../../hooks/useYourCustomHook';

const YourControl: React.FC<IYourControlProps> = (props) => {
  const {
} = props;

const [myItems, isError] = useYourCustomHook();

<section className={`${styles.mainProgress} ${hasTeamsContext ? styles.teams : ''}`}>
if (!isError) {
    return (
          {, idx) => {
            return (
                 { => {
                    return (
  } else {
    return <p>Error</p>;

export default YourControl

Hope that helps you


Joao Livio

João has over two decades of IT experience and holds several certifications, including Microsoft Certified Professional (MCP) and Microsoft Certified Technology Specialist (MCTS). He is also a Lean Specialist with expertise in Lean Management, Nintex, and other training programs from LinkedIn and Udemy, including exams related to Azure and the Power Platform. As a Consultant and Advisor for Modern Work, João assists clients in unlocking their digital potential and optimizing productivity and collaboration. His approach is agnostic to technology, focusing on practical solutions that align with business goals. He has consistently been recognized as a Microsoft Most Valuable Professional (MVP) for 10 consecutive years. His commitment to excellence extends beyond technical expertise; he also values consistency, mental health, creative thinking, teamwork, and fun at work. João believes that learning every day within a team context is the key to continuous improvement.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *