数か月前、UndertoneのWebアプリケーションの1つでデータテーブルを表示するReactコンポーネントを探していました。 Reactなどの高レベルライブラリに基づいていない以前のプロジェクトでは、 DataTables jQueryプラグインを使用しましたが、その柔軟性に非常に満足しています。 今、新しいアプリケーションにReactコンポーネントとして簡単に統合できる類似のものを探していました。
非常に広範な調査の後、2つのことを学びました。 第一に、両方のライブラリがDOMを制御するため、ReactでDataTablesを使用することは推奨されません。 第二に、Webアプリケーションに必要な柔軟性を提供するライブラリがありませんでした(私の研究のため)。 プロジェクトの完了期限が近づいており、私は何かを選択しなければなりませんでした。 人気のない方法でDataTablesをプロジェクトに統合することにしました。 結果は予想よりもはるかに良く、統合プロセス全体は実際には非常にスムーズでした。 以下のセクションでは、ReactとDataTablesの統合が機能するプロジェクト図について説明します。
プリセット
プロジェクトの足場にCreate-React-App (CRA)を使用します 。 CRAを初めて使用する場合、これは基本的に、構成せずにReactアプリケーションを構築するためのツールです。 最初に行う必要があるのは、CRAをインストールし(まだインストールしていない場合)、 create-react-app
を使用して新しいプロジェクトを初期化することcreate-react-app
(プロジェクトの初期化および開始方法の詳細については、 CRAのドキュメントを参照してください)。
jQueryおよびDatatablesモジュールを開発依存関係として追加することにより、インストールを完了します。
$ npm i --save-dev datatables.net jquery
モジュールのインストールが完了したら、CRAによって自動的に生成された不要なファイルをリポジトリから削除します。 この記事でここで作成するプロジェクトの最終結果は、GitHubのreact-datatablesリポジトリにあります。
シンプルなUI
非常にシンプルなインターフェースを実装します。 ユーザーには、対応するテキストフィールドに名前とエイリアスを入力できる入力領域があります。 「追加」ボタンをクリックすると、テキストフィールドに入力されたデータがデータテーブルに追加されます。 名前は各レコードの一意の「キー」です。ユーザーがすでに存在する名前を入力すると、ニックネームの新しいペアは作成されず、既存のペアのエイリアスのみがテーブルで更新されます。
DataTablesの設定
CRAによって作成された空のコンテンツを含むソースファイルが既にあります。 テーブルコンポーネントを含む新しいファイルを作成します-このコンポーネントは、テーブルのレンダリングと管理を行います。 まず、jQueryとDataTablesの両方をインポートしてバインドし、DataTablesがjQuerey関数にアクセスできるようにします。 これは、次の2行を使用して実行できます。
const $ = require('jquery'); $.DataTable = require('datatables.net');
テーブルに提供する名前とニックネームのペアから対応する値を抽出する2つの列を定義します。
const columns = [ { title: 'Name', width: 120, data: 'name' }, { title: 'Nickname', width: 180, data: 'nickname' }, ];
最後に、コンポーネント定義自体:
class Table extends Component { componentDidMount() { $(this.refs.main).DataTable({ dom: '<"data-table-wrapper"t>', data: this.props.names, columns, ordering: false, }) } componentWillUnmount() { $('.data-table-wrapper') .find('table') .DataTable() .destroy(true) } shouldComponentUpdate(nextProps) { if (nextProps.names.length !== this.props.names.length) { reloadTableData(nextProps.names) } else { updateTable(nextProps.names) } return false } render() { return ( <div> <table ref="main" /> </div> ) } }
いくつかのコメント。 render
関数では、1つのHTMLテーブル要素を作成します。 これはDataTablesの要件です。これは、DOMを設定するためにテーブル要素が必要だからです。 Reactは、table要素内にさらにDOMがあることを決して知りません。 Reactによる再試行が発生しないことを保証し、 shouldComponentUpdate
メソッドから常にfalse
を返しfalse
。 テーブル自体の初期化は、コンポーネントがマウントされたときに一度だけ実行する必要があります。これは、DataTablesにすべての内部DOM操作を残したいためです。 最後に、コンポーネントをアンマウントする必要があるときにテーブルを破棄する必要があります。 これは、対応するDataTables API呼び出しを使用してcomponentWillUnmount
メソッドで実行されます。
現在、Tableコンポーネントはprops.names
を介してデータをprops.names
ますが、名前を追加または更新する方法を実装していません。 これは次のセクションで行います。
テーブル更新
名前とニックネームのペアの配列を変更するには、2つの方法があります。 まず、新しい名前とニックネームのペアを追加します。 次に、既存の名前とニックネームのペアを、同じ名前と別のニックネームを持つ新しいペアに置き換えます。 これは、Tableコンポーネントの外部にある別のコンポーネントで実行されます。 (これらの更新の配布方法については詳しく説明しません。詳細については、 GitHub のプロジェクトリポジトリを参照してください。)ここでは、2つの異なる方法を使用した2種類の更新について説明します。
1)新しいニックネームのペアが追加されたら、テーブル全体をリロードします。
function reloadTableData(names) { const table = $('.data-table-wrapper').find('table').DataTable() table.clear() table.rows.add(names) table.draw() }
componentDidMount
(data-table-wrapper)で提供したクラスを使用して、標準jQueryセレクターを使用してテーブルインスタンスを検索します。 次に、以前のデータをすべて削除し、新しいデータをロードします(簡潔にするために、新しい名前とニックネームのペアは追加しませんでした-これは、1つまたは複数のペアを削除しても機能します)。
2)ペアが更新されたら、このペアを見つけて、変更されたデータの特定の部分(この例ではニックネームフィールド)を変更します。
function updateTable(names) { const table = $('.data-table-wrapper').find('table').DataTable() let dataChanged = false table.rows().every(function() { const oldNameData = this.data() const newNameData = names.find(nameData => { return nameData.name === oldNameData.name }) if (oldNameData.nickname !== newNameData.nickname) { dataChanged = true this.data(newNameData) } return true }) if (dataChanged) { table.draw() } }
データが変更された場合、または変更がユーザーに表示されない場合は、 draw
APIを使用してテーブルを再描画することを忘れないでください。
2つのケースを区別し、テーブルコンポーネントがReactに表示されるときに適切なメソッドを呼び出すだけです。 shouldComponentUpdate
コードでこれを行い、変更の種類を確認し、対応するメソッドを実行します。
shouldComponentUpdate(nextProps) { if (nextProps.names.length !== this.props.names.length) { reloadTableData(nextProps.names) } else { updateTable(nextProps.names) } return false }
現在、props.namesファイルのペアの数が変わるたびに、テーブル全体を再表示するか、対応する要素を更新します。 実際のアプリケーションでは、配列全体の内容が変更される可能性があり、要素の数は変更されない可能性があることに注意してください-この例では発生しません。
おわりに
DOMでDataTableを操作することからReactを保護している場合、ReactとDataTablesを統合することは間違いなく可能です。 この記事で実装したユースケースは非常に単純ですが、実際のプロジェクトに作業を統合するために必要なすべての構成要素を提供します。
PS
あなたの経験を共有してください-大量のデータを操作するためのソートとページネーションを備えたテーブルの機能を実装するためにどのReactコンポーネントが使用されていますか?