react-chartjs-2로 클릭 한 요소를 얻는 방법

개요



React 에 대한 세세한 설명은 필요 없을 것입니다. 지금 유행의 웹 프레임 워크입니다.
Chart.js 도 유명하네요. JavaScript로 작성된 그래프 그리기 라이브러리입니다.
react-chartjs-2 은, Chart.js 의 각종 그래프 요소를, React 의 Component 로서 쓸 수 있는 편리한 라이브러리입니다.

음, react-chartjs-2에서 산점도를 그렸습니다.



"Chart.js는 "범례 표시를 클릭했을 때 기본적으로 그 그래프를 숨기기"거동을 합니다.
그 때, 「어떤 그래프의 범례를 클릭했는지」를 조사하고 싶었습니다.
(아래의 이미지에서는, 「Verný+Valge 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

  • 같은 환경이었습니다.

    좋은 웹페이지 즐겨찾기