1

SPFX-ReactJS newbie here. Wondering how I should handle an empty list.

I am trying to connect my web part to a list and simply display them on my web part and automatically update the page as items are added or deleted from the list. As long as I have at least one item in my list when I start the workbench it appears to be working. If I add an item to my list, I see the item on my web part.

Cool, but if I then delete the last item in my list - it still appears in my web part.

How can I make that go away? Also, when I first start on the workbench, if my list is empty and I add an item - it will not automatically update.

Here is what my .tsx file currently looks like:

import * as React from 'react';
import styles from './ReactWebPartDemo.module.scss';
import { IReactWebPartDemoProps } from './IReactWebPartDemoProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { IReactWebPartDemoState } from "./IReactWebPartDemoStat";
import { SPHttpClient, SPHttpClientResponse } from "@microsoft/sp-http";

import { IColor } from '../IColor';
import { ColorList, IColorListProps } from './ColorList';
import { colProperties } from '@uifabric/utilities';
import { SPList, SPListItem } from '@microsoft/sp-page-context';

export default class ReactWebPartDemo extends React.Component<IReactWebPartDemoProps, IReactWebPartDemoState> {


  constructor(props: IReactWebPartDemoProps){
    super(props);
    this.state = {colors:[]};

  }
  private getColorsFromSPList(): Promise<IColor[]>{
    return new Promise<IColor[]>((resolve, reject) => {
      const endpoint: string = `${this.props.currentSiteUrl}/_api/lists/getbytitle('Colors')/items?select=Title`
      this.props.spHttpClient.get(endpoint, SPHttpClient.configurations.v1)
      .then((response: SPHttpClientResponse) => {
        return response.json();
      })
      .then((jsonResponse: any) => {
        let spListItemColors: IColor[] = [];
        for (let index = 0; index < jsonResponse.value.length; index++){
          spListItemColors.push({
            id: jsonResponse.value[index].Id,
            title: jsonResponse.value[index].Title
          });

          resolve(spListItemColors);
        }
      });
    });
  }

  public componentDidMount(): void{
    this.getColorsFromSPList()
      .then((spListItemColors: IColor[]) => {
        this.setState({colors: spListItemColors});         
      })  
   }  

   public componentDidUpdate():void
   {
    this.getColorsFromSPList()
      .then((spListItemColors: IColor[]) => {
        this.setState({colors: spListItemColors});         
      })  

   }

  public render(): React.ReactElement<IReactWebPartDemoProps> {         

    return (
        <div className={ styles.reactWebPartDemo }>
          <div className={ styles.container }>
            <div className={ styles.row }>
              <div className={ styles.column }>                                                      
                <ColorList colors={this.state.colors}/>           
            </div>
          </div>
        </div>
      </div>   

    )        
  }

  /*
  private _removeColor = (colorToRemove: IColor): void => {
    const newColors = this.state.colors.filter(color => color != colorToRemove);
    this.setState({colors: newColors });    
  }
  */

}

I'm working on getting the SPFx debug feature working. In the meantime here is what my ColorList component looks like (ColorList.tsx)

import * as React from 'react';
import {IColor} from '../IColor';
import styles from './ReactWebPartDemo.module.scss';


import { List } from 'office-ui-fabric-react/lib/List';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
import { getItemStyles } from 'office-ui-fabric-react/lib/components/ContextualMenu/ContextualMenu.classNames';

export type RemoveColorCallback = (color: IColor) => void;

export interface IColorListProps {
    colors: IColor[];  
}


export class ColorList extends React.Component<IColorListProps, {}>{

    public render(): React.ReactElement<IColorListProps>{


                return (           
                    <List items={ this.props.colors }           
                        onRenderCell={ this._onRenderListCell }/>       
                );

    }

    private _onRenderListCell = (color: IColor, index: number | undefined): JSX.Element => {
        return (                   
            <div className={styles.title}>
                { color.title }  
            </div>
        )         
    }
}
1
  • It's probably throwing an error inside the ColorList component. Can you debug it? Commented Jul 3, 2019 at 15:29

1 Answer 1

0

An empty list means no colors in state, am I right? So just a small insert in your render method should work I guess:

public render(): React.ReactElement<IReactWebPartDemoProps> {         

    return (
        <div className={ styles.reactWebPartDemo }>
          <div className={ styles.container }>
            <div className={ styles.row }>
              <div className={ styles.column }>                                                      
                this.state.colors == null ? <span> No items available </span> : <ColorList colors={this.state.colors}/>           
            </div>
          </div>
        </div>
      </div>   

    )        
  }
1
  • Thanks for the suggestion, I tried that and I'm getting the same behavior....everything seems to work the way I want it to unless there is nothing for the webpart to show. I still have to do a manual refresh of the page if I delete/mark the last list item to not display.
    – cwk1999
    Commented Jul 5, 2019 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.