React + SPFx 我得到我的空列表,只能通过操作它们来获取项目

React + SPFx I get my empty list and only get the items by manipulating them

我正在创建一个具有过滤和搜索功能的 Sharepoint 列表查看器。当 WebPart 加载时,列表显示为空,并且仅在我进行搜索或筛选时显示项目。当我删除搜索或过滤时,所有项目都会出现。如何从头开始显示所有项目?

initial state

after typing "a" (as an example)

childclass代码:

export class MisContactos extends React.Component<any, any>{

  private _selection: Selection;

  constructor(props: {}) {

    super(props);
    
    var misItems = this.props._items;
    const columns: IColumn[] = [
      {
        key: 'column1',
        name: 'ID',
        fieldName: 'ID',
        minWidth: 50,
        maxWidth: 350,
        isRowHeader: true,
        isResizable: true,
        isSorted: true,
        isSortedDescending: false,
        sortAscendingAriaLabel: 'Sorted A to Z',
        sortDescendingAriaLabel: 'Sorted Z to A',
        onColumnClick: this._onColumnClick,
        data: 'string',
        isPadded: true
      },
      {
        key: 'column2',
        name: 'Name',
        fieldName: 'Title',
        minWidth: 110,
        maxWidth: 350,
        isRowHeader: true,
        isResizable: true,
        isSorted: true,
        isSortedDescending: false,
        sortAscendingAriaLabel: 'Sorted A to Z',
        sortDescendingAriaLabel: 'Sorted Z to A',
        onColumnClick: this._onColumnClick,
        data: 'string',
        isPadded: true
      },
      {
        key: 'column3',
        name: 'Nachname',
        fieldName: 'Nachname',
        minWidth: 110,
        maxWidth: 350,
        isRowHeader: true,
        isResizable: true,
        isSorted: true,
        isSortedDescending: false,
        sortAscendingAriaLabel: 'Sorted A to Z',
        sortDescendingAriaLabel: 'Sorted Z to A',
        onColumnClick: this._onColumnClick,
        data: 'string',
        isPadded: true
      },
      {
        key: 'column4',
        name: 'Firmen',
        fieldName: 'Company',
        minWidth: 110,
        maxWidth: 350,
        isRowHeader: true,
        isResizable: true,
        isSorted: true,
        isSortedDescending: false,
        sortAscendingAriaLabel: 'Sorted A to Z',
        sortDescendingAriaLabel: 'Sorted Z to A',
        onColumnClick: this._onColumnClick,
        data: 'string',
        isPadded: true
      },
      {
        key: 'column5',
        name: 'Email',
        fieldName: 'Email',
        minWidth: 150,
        maxWidth: 350,
        isRowHeader: true,
        isResizable: true,
        isSorted: true,
        isSortedDescending: false,
        sortAscendingAriaLabel: 'Sorted A to Z',
        sortDescendingAriaLabel: 'Sorted Z to A',
        onColumnClick: this._onColumnClick,
        data: 'string',
        isPadded: true
      },
      {
        key: 'column6',
        name: 'Land',
        fieldName: 'Land',
        minWidth: 100,
        maxWidth: 350,
        isRowHeader: true,
        isResizable: true,
        isSorted: true,
        isSortedDescending: false,
        sortAscendingAriaLabel: 'Sorted A to Z',
        sortDescendingAriaLabel: 'Sorted Z to A',
        onColumnClick: this._onColumnClick,
        data: 'string',
        isPadded: true
      },
      {
        key: 'column7',
        name: 'Abteilung',
        fieldName: 'Abteilung',
        minWidth: 100,
        maxWidth: 350,
        isRowHeader: true,
        isResizable: true,
        isSorted: true,
        isSortedDescending: false,
        sortAscendingAriaLabel: 'Sorted A to Z',
        sortDescendingAriaLabel: 'Sorted Z to A',
        onColumnClick: this._onColumnClick,
        data: 'string',
        isPadded: true
      }
    ];

    this._selection = new Selection({
      onSelectionChanged: () => {
        this.setState({
          selectionDetails: this._getSelectionDetails()
        });
      }
    });

    this.state = {
      items: misItems,
      columns: columns,
      selectionDetails: this._getSelectionDetails(),
      isModalSelection: false,
      isCompactMode: false      
    };

  } 

  public render() {

    var { columns, isCompactMode, items, selectionDetails, isModalSelection, paises } = this.state;

    return (<Fabric>
      <div className={classNames.controlWrapper}>
        <Toggle
          label="Enable compact mode"
          checked={isCompactMode}
          onChange={this._onChangeCompactMode}
          onText="Compact"
          offText="Normal"
          styles={controlStyles}
        />
        <Stack>
          
          <Checkbox
            label="Spanien"
            value="Spanien"
            styles={controlStyles}
            onChange={ e => {this._onSpanien} }
            defaultChecked = {false}
          />
          <Checkbox 
            label="Deutschland"
            styles={controlStyles}
            onChange={this._onDeutschland}
            defaultChecked = {false}
          />
        </Stack>

        <Toggle
          label="Toogle"
          checked={isModalSelection}          
          onText="Modal"
          offText="Normal"
          styles={controlStyles}
        />
        
        <TextField label="Filter by name" onChange={this._onChangeText} styles={controlStyles} />
      </div>
      <div className={classNames.selectionDetails}>{selectionDetails}</div>
      <MarqueeSelection selection={this._selection}>
        <DetailsList
          items={items}
          compact={isCompactMode}
          columns={columns}
          selectionMode={isModalSelection ? SelectionMode.multiple : SelectionMode.none}
          
          setKey="set"
          layoutMode={DetailsListLayoutMode.justified}
          isHeaderVisible={true}
          selection={this._selection}
          selectionPreservedOnEmptyClick={true}
          onItemInvoked={this._onItemInvoked}
          enterModalSelectionOnTouch={true}
          ariaLabelForSelectionColumn="Toggle selection"
          ariaLabelForSelectAllCheckbox="Toggle selection for all items"
          checkButtonAriaLabel="Row checkbox"
        />
      </MarqueeSelection>
    </Fabric>
    );
  } 
  
  
  public componentDidUpdate(previousProps: any, previousState: IDetailsListDocumentsState) {
    if (previousState.isModalSelection !== this.state.isModalSelection && !this.state.isModalSelection) {
      this._selection.setAllSelected(false);
    }
  }  

  
  private _onChangeText = (ev: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, text: string): void => {
    var misItems2: IlistContactosItems[];
    misItems2 = JSON.parse(JSON.stringify(this.props._items));
    console.log("pasa por onChangeText");

    this.setState({
      items: text ? misItems2.filter(i => i.Title.toLowerCase().indexOf(text) > -1) : misItems2
    });
  }  
  
}

export default MisContactos

和父亲class代码:

export default class AaReact1 extends React.Component<IAaReact1Props, any> {

  constructor(props: IAaReact1Props, any) {
    super(props);

    this.state = {
      links: []
    };
  }
  public componentDidMount() {
    this.getContactosListData();
  }

  public render(): React.ReactElement<IAaReact1Props> {
    console.log("render");
    return (
      <div className={styles.aaReact1}>
        <MisContactos header={this.props.description} _items={this.state.links} />
      </div>
    );
  }
  private getContactosListData(): Promise<any> {
    return this.props.spClientContext.get("https://Mock.sharepoint.com/sites/yo/_api/web/lists/getbytitle('Kontakte')/items?Odata=minimal",
      SPHttpClient.configurations.v1).then((response: SPHttpClientResponse) => {
        return response.json();
      }).then(data => {
        data=JSON.parse(JSON.stringify(data));
        this.setState({ links: data.value });

      });
  }

}

感谢您的宝贵时间和帮助。

作为异步请求,webpart第一次渲染时没有数据,我会针对这个场景展示一个'data loading'信息,你可以查看我在github中的demo webpart。 https://github.com/OS-Lee/FileViewCounter/blob/master/src/webparts/fileViewCounter/components/FileViewCounter.tsx

return (      
      <div className={ styles.fileViewCounter }>
        <div className={ styles.container }>
          <div className={ styles.row }>
            <div className={ styles.column }>              
              <table className="tree">
                <thead>
                    <tr>
                        <th className={styles.THWidth}>Folder/File</th>
                        <th >Views</th>
                        <th >Viewers</th>
                    </tr>
                </thead>                
                { this.state.FileViewResult
                    ? <tbody dangerouslySetInnerHTML={{ __html: this.state.FileViewResult}}></tbody>
                    : <tr><td align={"center"} colSpan={3}>Data Loading...</td></tr>
                 }                
            </table>          
            </div>
          </div>
        </div>
      </div>
    );

我已经解决了这个问题,我将 post 我的解决方案,以防有人遇到同样的问题,这可以帮助他们。

我添加了一个加载组件作为过渡元素。从 Sharepoint 列表加载项目时,此元素保留在前台。

export default class AaReact1 extends React.Component<IAaReact1Props, any> {
  constructor(props: IAaReact1Props, any) {
    super(props);

    this.state = {
      links: [],
      loading: true
    };
  } 
  public render(): React.ReactElement<IAaReact1Props> {
    console.log("render padre");
    if (this.state.loading) {
      this.getContactosListData();
      return(<Loading />)
    }else{
    return (
      <div className={styles.aaReact1}>
        <MisContactos header={this.props.description} _items={this.state.links} />
      </div>
    );
  }}
  
  private getContactosListData(): Promise<any> {
    return this.props.spClientContext.get("https://Mock.sharepoint.com/sites/yo/_api/web/lists/getbytitle('Kontakte')/items?Odata=minimal&$top=5000",
      SPHttpClient.configurations.v1).then((response: SPHttpClientResponse) => {
        return response.json();
      }).then(data => {
        data = JSON.parse(JSON.stringify(data));
        this.setState({ links: data.value, loading:false });
      });
  }
}