Getting error 'response.map is not a function' trying to map a list items with managed metadata fields in spfx react solution

sharepoint.stackexchange https://sharepoint.stackexchange.com/questions/251859

Pergunta

I am trying to get items from a links list with managed metadata. I am getting an error 'response.map is not a function'. I have used the sample from this answer to get the data using RenderListDataAsStream (SPFX - cannot get actual label of managed metadata list field). I can get the data - I can see it in the console - so I know that the caml query works, but can't seem to map the results. I get the error 'response.map is not a function'.

There is my code:

import * as React from 'react';
import styles from './LinksWp.module.scss';
import { ILinksWpProps } from './ILinksWpProps';
import { escape } from '@microsoft/sp-lodash-subset';
import pnp from "sp-pnp-js";
import { ClassListItems } from './ClassListItem';
import { ISPListItem } from './IListItems';
import { sp, RenderListDataParameters, RenderListDataOptions } from '@pnp/sp';

export default class LinksWp extends React.Component<ILinksWpProps, any> {

public constructor(props:ILinksWpProps,any)
{
super(props);
this.state={
items:[]
}
}



  public render(): React.ReactElement<ILinksWpProps> {
    return (
      <div><h1>{this.props.description}</h1>
      <div>{this.state.items.map(function(item:ISPListItem){
      return(
      <div>
       <span><a href={item.URL.Url}>{item.URL.Description}</a></span>
      </div>
    )

})}</div>


      </div>

    );
  }

public componentDidMount(){

  this._getListItems();
}

private _getListItems():void

{


pnp.sp.web.lists.getByTitle('Quick Links').renderListDataAsStream({
  RenderOptions: RenderListDataOptions.ListData,
  ViewXml :  `<View><Query><Where><Eq><FieldRef Name='Function' />
  <Value Type='TaxonomyFieldTypeMulti'>Group IT</Value></Eq></Where></Query><ViewFields>
  <FieldRef Name='URLwMenu2' /><FieldRef Name='Region' />
  <FieldRef Name='Function' /><FieldRef Name='Geography' />
  </ViewFields><QueryOptions />
  </View>`
}).then
((response)=>{
  console.log(response)
   **let listItemCollection = response.map(item=>new ClassListItems(item));** // this is where I get the error
   this.setState({items: listItemCollection});
  }

)

}
}

I have defined an interface and a class for this as well

import { ISPListItem } from "./IListItems"

export class ClassListItems {

public URL;
public Region;
public Function;
public Geography;

constructor(item: ISPListItem) {

this.URL = item.URL;
this.Region = item.Region;
this.Function = item.Function;
this.Geography = item.Geography;

}
}

export interface ISPListItem{

URL;
Region : string;
Function : string;
Geography : string;

}
Foi útil?

Solução 2

I worked out how to do the last bit - to display multi value managed metadata values. I created an additional interface and a class for a label

export interface ISPLabel{

    Label : any;
    TermID: any;


    }

export class ClassListItemLabels {

    public Label: any;
    public TermID: any;


    constructor(i: ISPLabel) {

    this.Label = i.Label;
    this.TermID = i.TermID;

    }
    }

The I can get the labels out mapping the labels to the interface and class. I think I can use .map() as the property is an array

     <div>{
         this.state.items.sort( (a, b) =>{ 
          return a.Desc == b.URL.Desc ? 0 : a.Desc < b.Desc ? -1 : 1;
        })


        .map(function(item:ISPListItem){
      return(
      <div>
        <ul className={styles.myUl}>
          <li className={styles.myUlLi}><a href={item.URL}>{item.Desc}</a></li> 

          <span><ul className={styles.ulLables}>{
            /*  Getting the Labels Out   */
            item.Function1

            .map(function(i:ISPLabel){
     return(
    <li>{i.Label}; </li>

     )
            }

            )
          }</ul></span>
        </ul>

      </div>
    )

})}</div>

Outras dicas

As mentioned in comments, the data returned is in the form of a javascript object. Now, we can't use map function over an object, it will only work with arrays. That array is present as response.Row in the AJAX response.

So, modify your code as below and then use that to set the state:

//code omitted for brevity

}).then
((response: any)=>{
  console.log(response)
   let listItemCollection = response.Row.map(item=>new ClassListItems(item));
   this.setState({items: listItemCollection});
  }

)

To get URL description, you should modify the interfaces as below:

export interface ISPListItem {

  URL: any;  
  Desc: any;
  Region: string;
  Function: string;
  Geography: string;

}

export class ClassListItems {

  public URL: any;
  public Desc : string
  public Region: string;
  public Function: string;
  public Geography: string;

  constructor(item: ISPListItem) {

    this.URL = item.URL;
    this.Desc = item["URL.desc"];
    this.Region = item.Region;
    this.Function = item.Function;
    this.Geography = item.Geography;

  }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a sharepoint.stackexchange
scroll top