react-chartjs-2でクリックした要素を取得する方法について
概要
Reactについて細かい説明は必要ないでしょう。今流行りのWebフレームワークです。
Chart.jsも有名ですね。JavaScriptで書かれたグラフ描画用ライブラリです。
react-chartjs-2は、Chart.jsの各種グラフ要素を、ReactのComponentとして書ける便利なライブラリです。
さて、react-chartjs-2で私は散布図を描画していました。
で、Chart.jsは「凡例の表示をクリックした時、デフォルトではそのグラフを非表示にする」挙動をします。
その際、「どのグラフの凡例をクリックしたか」を調べたいと思いました。
(下の画像では、「Верный+バルジ4」のグラフが非表示になっています)
Chart.jsのドキュメントによると、凡例をクリックした際の標準の処理が載っています。その際、クリックしたグラフの情報が引数に乗るので、これを読み取れれば目的が達成されるのではないかと考えました。
しかし、 そのコード中のthisってどうやって参照するんだよ 問題が目の前に立ちはだかります。Reactでは「Class ComponentやFunctional Component内にJSXを書いて仮想DOMを表現する」ので、thisの意味が「class本体」や「グローバルのthis」のようになります。つまり、「JSX内のタグの参照(目的とするthis)」をどうやって取得するのかが重要なのです。
解決策
react-chartjs-2において散布図は、<Scatter>
という独自タグで表現されています。その属性(Props)の中にはref
というものがあり、これが当該タグの参照となります。参照を保持するには、React Hooks的に考えるとuseRef
を使うべきです。
const OutputGraph: React.FC<{params: IGraphParam[]}> = ({params}) => {
// <Scatter>への参照情報
const scatterElement = React.useRef<Scatter>(null);
(略)
return (
// 参照を利用される当該タグ
<Scatter width={450} height={450} data={graphData}
ref={scatterElement} onElementsClick={onClickGraph}
options={{
elements: { line: { tension: 0 } },
scales: {
xAxes: [{ scaleLabel: { display: true, labelString: '最終攻撃力' }, }],
yAxes: [{ scaleLabel: { display: true, labelString: '大破率(%)' }, }]
},
showLines: true
}} />
);
}
こうしてオブジェクト自体の参照を取ってしまえば、後はそこから辿っていけば、目的とする情報を取得できます。
const onClickGraph = () => {
// 参照を取得する
const scatterObject = scatterElement.current;
// ここで丁寧にnullチェックしているのは、scatterObjectが↑の段階だと
// Scatter | null型なので、スマートキャストする必要があることから
if (scatterObject == null) {
return;
}
// ここで一旦anyにキャストしているのは、scatterObject.chartInstanceは
// Chart型と判断されているのに、@types/chart.jsの定義によると、
// なぜかlegendプロパティが生えていなかったから
// (キャストしないとエディタがエラーを出してコンパイルできない)
const temp: any = scatterObject.chartInstance;
// 強引にanyにキャストしたご利益で、legendプロパティ以下を取得できている
// temp.legend.legendItemsの中身はもっと複雑な型の配列(AoS)だが、
// 必要な部分だけ読み取ることで記述量を減らしている
const legendItems: Array<{text: string, hidden: boolean}> = temp.legend.legendItems;
// 読み取りは終わったので後はデータ加工のみ
const ignoreNames = legendItems.filter(item => item.hidden).map(item => item.text);
// useState()から引っ張ってきた上書き用メソッドを利用する
// (今回の記事とは無関係)
setGraphData(createGraphData(ignoreNames));
};
ちなみに<Scatter>
にはonElementsClick
属性があり、名前からしてクリックしたグラフの情報を引数から渡してくれる……そんなふうに考えていた時期が私にもありました。実際にはクリックしても[]
しか引数のe: any
に渡されないので、「クリックした」ということしか読み取れないというね! どうしてこうなった!!!
備考
package.jsonによると、
- react: 16.8.2
- chart.js": 2.7.3
- react-chartjs-2: 2.7.4
- @types/chart.js: 2.7.45
といった環境でした。
Author And Source
この問題について(react-chartjs-2でクリックした要素を取得する方法について), 我々は、より多くの情報をここで見つけました https://qiita.com/YSRKEN/items/938d33d3db547efb10fc著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .