SingleFieldListのChipのLinkを無効化・カスタマイズする方法

はじめに

React Adminを使用していると、単一のフィールドに複数の値を表示させたいケースがあります。

そんなとき、SingleFieldListコンポーネントは便利です。

こんな感じでChipで表示するので、/などで区切るよりもスマートに表示できます。

ただ、デフォルトの動作では各項目がリンクになっており、クリックするとページ遷移してしまいます。

今回は、この挙動を変更し、リンクを無効化する方法、さらにはリンクをカスタマイズする方法をまとめます。

問題の背景

最近、あるプロジェクトで以下のような要件がありました: - 単一のフィールドに存在する複数のフィールドを一覧表示する - 各タグはChipコンポーネントとして表示する - タグをクリックしてもページ遷移はしない

SingleFieldListを使用すると、複数のフィールドの一覧表示は簡単に実装できます。がしかし、デフォルトではタグがクリック可能なリンクになってしまい、意図しないページ遷移が発生するという問題がありました。

SingleFieldListの基本的な使用方法

まず、問題の原因となっているSingleFieldListの基本的な使用方法を見てみましょう。

import { List, SingleFieldList, ChipField } from 'react-admin';

export const TagList = () => (
    <List>
        <SingleFieldList>
            <ChipField source="name" />
        </SingleFieldList>
    </List>
);

このコードでは、各タグが編集ページへのリンクとして機能してしまいます。

リンクを無効化する方法

SingleFieldListコンポーネントにはlinkTypeというプロパティがあります。これをfalseに設定することで、リンクを無効化できます。

修正後のコードは以下のようになります:

import { List, SingleFieldList, ChipField } from 'react-admin';

export const TagList = () => (
    <List>
        <SingleFieldList linkType={false}>
            <ChipField source="name" />
        </SingleFieldList>
    </List>
);

この変更により、タグはクリック可能なリンクではなく、単なる表示用のChipとなります。

リンクを個別に指定する方法

リンクを完全に無効化するのではなく、カスタムのリンク先を指定したい場合もあるでしょう。

linkTypeプロパティに関数を渡すことで、各アイテムに対して個別にリンクを指定することができます。

以下は、各タグをクリックした際に、そのタグに関連する投稿一覧ページに遷移するようにカスタマイズした例です:

import { List, SingleFieldList, ChipField } from 'react-admin';

export const TagList = () => (
    <List>
        <SingleFieldList
            linkType={(record, id) => `/posts?filter=${JSON.stringify({ tags: id })}`}
        >
            <ChipField source="name" />
        </SingleFieldList>
    </List>
);

この例では、linkTypeプロパティに関数を渡しています。この関数は各レコードとそのIDを引数として受け取り、リンク先のURLを返します。ここでは、各タグをクリックすると、そのタグが付けられた投稿の一覧ページにフィルターをかけて遷移するようになっています。

こうすることで、柔軟にリンクを指定できます。

まとめ

SingleFieldListのリンク機能は多くの場合便利ですが、今回のようにリンクが不要なケースや、カスタムのリンク先が必要なケースもあります。linkTypeプロパティを適切に使用することで、簡単にリンクを無効化したり、カスタマイズしたりすることができ、意図した挙動を実現できます。

React Adminはコンポーネントの多さも去ることながらPropsも豊富なので、柔軟にUIを構築できます。 とりあえず「これできるか?」と思ったらドキュメントを探ってみるのが良いです。

参考リソース