リストからデータを読むのに、どうやってSharePointに「中身をください」とお願いすればいいのでしょう?
SPFxには、SharePointと安全に通信するための専用の道具 SPHttpClient が用意されています。これを使えば、面倒な認証を意識せずに、リストの中身をJSONで受け取れます。この記事で、その取得と描画を一気に実装します。
手順の全体像
やることは3つです。
- 受け取るデータの「型」を決める(
IAnnouncement) - React部品が リストを取得 して状態に持つ
- 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>
);
}
}
コードのキモを、日本語で追ってみましょう。
url… 「このサイトの_api/web/lists/getByTitle('お知らせ')/itemsから、Title・Body・PublishDateを、掲載日の新しい順で」という"注文書"spHttpClient.get(...)… その注文書をSharePointへ送る。認証はSPFxが面倒を見てくれるres.json()… 返事をJSONとして受け取る。リストの項目はjson.valueの中に配列で入っているsetState({ items })… 受け取った項目を状態に保存。するとrender()が再実行され、一覧が描かれる
componentDidMount は「画面に出た瞬間に一回だけ呼ばれる」お約束の場所。だからデータ取得の定位置なんだ。取得は時間がかかるから、最初は空っぽ(items:[])で表示して、届いたら setState で描き直す——この"あとから届く"感覚がReactらしいところだよ。
④ 本体(.ts)から context とリスト名を渡す
最後に、Webパーツ本体 ListViewerWebPart.ts の render() で、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。赤いエラーが出たら、列の内部名やスペルミスを見直してください。
この記事のまとめ
- SharePointとの通信は専用の道具
SPHttpClientを使う(認証はSPFx任せ) - データ取得の定位置は React の
componentDidMount - 取得したデータは
setStateで保存 →render()が再実行され画面に出る - 本体(.ts)から
contextとlistNameをReactへ渡す
一覧表示ができました。でも今は表示するリスト名が直書き。次の記事で、これを設定パネルから変えられるようにして、部品として"使える"ものに仕上げます。
- SPHttpClient
- SharePointと安全に通信する専用クライアント。認証を意識せずAPIを呼べる
- _api/web/lists/getByTitle('...')/items
- リストの項目を取得するSharePoint REST APIのURL
- componentDidMount
- Reactで「画面に出た直後」に一度呼ばれるメソッド。データ取得の定位置
- setState
- Reactの状態を更新する命令。呼ぶと画面が描き直される