STAGE 04 — 4-2 / 実装する

リストの中身を取得して描く

考えてみよう

リストからデータを読むのに、どうやってSharePointに「中身をください」とお願いすればいいのでしょう?

SPFxには、SharePointと安全に通信するための専用の道具 SPHttpClient が用意されています。これを使えば、面倒な認証を意識せずに、リストの中身をJSONで受け取れます。この記事で、その取得と描画を一気に実装します。

手順の全体像

やることは3つです。

  1. 受け取るデータの「型」を決める(IAnnouncement
  2. React部品が リストを取得 して状態に持つ
  3. React部品が、取得した項目を 一覧として描く

① データの型を決める

まず、1件のお知らせがどんな形かを型で表します。components フォルダに IAnnouncement.ts を作りましょう。列の内部名(前記事で確認した Title / Body / PublishDate)に合わせます。

export interface IAnnouncement {
  Title: string;
  Body: string;
  PublishDate: string;
}

② React部品が受け取る値の型

React部品には、通信の道具(context)対象リスト名 を渡します。IListViewerProps.ts をこう変えます。

import { WebPartContext } from '@microsoft/sp-webpart-base';

export interface IListViewerProps {
  context: WebPartContext;
  listName: string;
}

③ 取得して描くReactコンポーネント

いよいよ本丸です。components/ListViewer.tsx を、次のように書き換えます。

import * as React from 'react';
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
import { IListViewerProps } from './IListViewerProps';
import { IAnnouncement } from './IAnnouncement';

interface IListViewerState {
  items: IAnnouncement[];
  error: string;
}

export default class ListViewer
  extends React.Component<IListViewerProps, IListViewerState> {

  constructor(props: IListViewerProps) {
    super(props);
    this.state = { items: [], error: '' };
  }

  // 画面に出た直後に、一度だけデータを取りに行く
  public componentDidMount(): void {
    this._loadItems();
  }

  private _loadItems(): void {
    const url =
      `${this.props.context.pageContext.web.absoluteUrl}` +
      `/_api/web/lists/getByTitle('${this.props.listName}')/items` +
      `?$select=Title,Body,PublishDate&$orderby=PublishDate desc`;

    this.props.context.spHttpClient
      .get(url, SPHttpClient.configurations.v1)
      .then((res: SPHttpClientResponse) => res.json())
      .then((json: { value: IAnnouncement[] }) => {
        this.setState({ items: json.value });
      })
      .catch((e: Error) => {
        this.setState({ error: '読み込みに失敗しました:' + e.message });
      });
  }

  public render(): React.ReactElement<IListViewerProps> {
    const { items, error } = this.state;
    if (error) { return <p>{error}</p>; }

    return (
      <div>
        <h2>お知らせ</h2>
        <ul>
          {items.map((item, i) =>
            <li key={i}>
              <strong>{item.Title}</strong>
              ({item.PublishDate ? item.PublishDate.substring(0, 10) : ''})
              <br />{item.Body}
            </li>
          )}
        </ul>
      </div>
    );
  }
}

コードのキモを、日本語で追ってみましょう。

ゆみちゃん
ゆみ

componentDidMount は「画面に出た瞬間に一回だけ呼ばれる」お約束の場所。だからデータ取得の定位置なんだ。取得は時間がかかるから、最初は空っぽ(items:[])で表示して、届いたら setState で描き直す——この"あとから届く"感覚がReactらしいところだよ。

④ 本体(.ts)から context とリスト名を渡す

最後に、Webパーツ本体 ListViewerWebPart.tsrender() で、React部品に値を渡します。リスト名は、いったん 'お知らせ' を直書きします(次の記事で設定可能にします)。

public render(): void {
  const element: React.ReactElement<IListViewerProps> =
    React.createElement(ListViewer, {
      context: this.context,
      listName: 'お知らせ'   // ← 次の記事で設定パネルから変えられるようにする
    });
  ReactDom.render(element, this.domElement);
}

これで、「リストから読む → Reactで描く」が一本につながりました。

やってみよう

ここまで保存すると、heft start が自動でビルドし直します。ターミナルにエラーが出ていないかを確認しましょう。

確認ポイント

注意: 実際のリストのデータが表示されるのは、実SharePoint上で動く「ホストされたワークベンチ」でのことです(次のSTAGE 05で確認します)。まずはビルドがエラーなく通ることを確認できればOK。赤いエラーが出たら、列の内部名やスペルミスを見直してください。

この記事のまとめ

一覧表示ができました。でも今は表示するリスト名が直書き。次の記事で、これを設定パネルから変えられるようにして、部品として"使える"ものに仕上げます。

用語メモ
SPHttpClient
SharePointと安全に通信する専用クライアント。認証を意識せずAPIを呼べる
_api/web/lists/getByTitle('...')/items
リストの項目を取得するSharePoint REST APIのURL
componentDidMount
Reactで「画面に出た直後」に一度呼ばれるメソッド。データ取得の定位置
setState
Reactの状態を更新する命令。呼ぶと画面が描き直される