How to update the state/props of a custom visualisation component after the initial render?

(Eoin) #1

I have been trying to create a custom visulaisation for Kibana 6.5.4. I have written a custom component, request and response handler. I get the data for my visualisation from the props.visData attribute. However this data only gets updated once, when the component initially renders. If I change the time period via kibana's time picker and make the request again, I can see that my response handler has the new data, but that this is not passed down into my visualisation component.

In my visualisation component's constructor I am adding a variable called skyplotData to the component state, and setting its value to the props.visData attribute. I then use skyplotData to populate the plot of my visualisation.

How can I ensure that the state is updated when the user changes the time period via the time picker on Kibana?

Code below is that of my visualisation component:

import React from 'react';
import Plot from 'react-plotly.js';

import {
  EuiPage,
  EuiPageHeader,
  EuiTitle,
  EuiPageBody,
  EuiPageContent,
  EuiPageContentHeader,
  EuiPageContentBody,
  EuiText
} from '@elastic/eui';


const plotLayout = {
  showlegend: true,
  width: 800, height: 800,
  polar: {
    radialaxis: {
      range: [90, 0], //Sets x axis range. Default is 0 to largest value in the dataset
      tickmode: 'array',
      tickvals: [90, 75, 60, 45, 30, 15, 0], //Sets how many ticks to show on the plot
      tickfont: {
        size: 8
      }
    },
    angularaxis: {
      tickfont: {
        size: 8
      },
      direction: 'clockwise'
    }
  }
};

const plotConfig = { displayModeBar: false }; //Hides options to zoom, screenshot etc.

export class SelfChangingComponent extends React.Component {
  constructor(props) {
    super(props);
    //Set the skyplot data in the component state
    this.state = {
      skyplotData: props.visData,
      plotLayout,
      plotConfig
    };
    console.log('visData: ', this.props.visData);
  }

  render() {
    return (
      <EuiPage>
        <EuiPageBody>
          <EuiPageContent>
            <EuiPageContentHeader>
              <EuiTitle>
                <h2>Skyplot</h2>
              </EuiTitle>
            </EuiPageContentHeader>
            <EuiPageContentBody>
              <Plot
                data={this.state.skyplotData}
                layout={this.state.plotLayout}
                config={this.state.plotConfig}
              />
            </EuiPageContentBody>
          </EuiPageContent>
        </EuiPageBody>
      </EuiPage>
    );
  }

  componentDidMount() {
    this.props.renderComplete();
  }

  componentDidUpdate() {
    this.props.renderComplete();
  }
}

From what I understand about React, state changes are usually pushed down from the parent component, but I don't understand how that works in this case, as I don't have a parent component. I have just registered a new visualisation by using VisFactory.createReactVisualization, and added my component to it using:

visConfig: {
      component: SelfChangingComponent,
(Eoin) #2

Can anyone help with this? I can't find any solution to the issue. It's the final issue I'm having with my custom visualisation

(Joe Fleming) #3

@ppisljar @timroes Can one of you provide any insight here? It's been many years since I've had to deal with Kibana visualizations...

(Tim Roes) #4

Hi,

the problem is, that you're expecting the constructor to be called again in a React component when it's props changes. That is not how React work :slight_smile: You need to use the appropriate lifecycle methods (https://reactjs.org/docs/react-component.html) to transfer changed props into your state if you need that. Please be aware that Kibana 6.5.4 ran on React 16.3, so you don't have getDerivedStateFromProps yet, so instead you'll need to use the componentWillUpdate method instead.

Cheers,
Tim