Conseil
Cette leçon fait partie d'un cours qui vous apprend à créer une visualisation personnalisée sur la plateforme New Relic.
Utilisez les visualisations personnalisées New Relic pour afficher vos données, qu'elles proviennent de la base de données New Relic ou d'une source externe, de manière unique et distincte des graphiques proposés par la plateforme New Relic.
Dans cette leçon, vous créez une visualisation qui affiche vos données dans l'un des deux types de graphiques : RadarChart ou Treemap. Vous implémentez ensuite un composant SegmentedControl du SDK New Relic One, qui vous permet d'alterner entre les deux types de graphiques. En fin de compte, cela vous donne la liberté de visualiser vos données de manière dynamique, ce qui n'est pas possible avec les offres de base de New Relic.
Conseil
Si vous êtes perdu dans le projet de code et que vous souhaitez voir à quoi devraient ressembler les fichiers lorsque vous avez terminé chaque leçon, consultez le projet de cours sur Github.
Avant de commencer
Enfin, si vous ne l’avez pas déjà fait :
- Inscrivez-vous pour un compte New Relic
 - Installer Node.js
 - Suivez les étapes du démarrage rapide
nr1pour installer et configurer la CLI 
Créez votre visualisation
Assurez-vous que vous travaillez avec la dernière version de la CLI New Relic :
$nr1 updateCréez une visualisation, appelée radar-or-treemap, dans un Nerdpack, appelé alternate-viz:
$nr1 create --type visualization --name radar-or-treemap✔ You’re trying to create a visualization outside of a Nerdpack.  We’ll create a Nerdpack for you—what do you want to name it? … alternate-viz✔  nerdpack created successfully!   nerdpack alternate-viz is available at "./alternate-viz"✔  visualization created successfully!   visualization radar-or-treemap is available at "./alternate-viz/visualizations/radar-or-treemap"Conseil
Si vous recevez un RequestError pour un certificat auto-signé lorsque vous exécutez nr1 create, vous devrez peut-être ajouter un certificat à la chaîne de certificats du nœud.
En conséquence, vous disposez d'un nouveau répertoire visualizations/radar-or-treemap sous alternate-viz:
$cd alternate-viz$ls visualizations/radar-or-treemapindex.js    nr1.json    styles.scssimport React from 'react';import PropTypes from 'prop-types';import {  Radar,  RadarChart,  PolarGrid,  PolarAngleAxis,  PolarRadiusAxis,} from 'recharts';import {  Card,  CardBody,  HeadingText,  NrqlQuery,  Spinner,  AutoSizer,} from 'nr1';
export default class RadarOrTreemapVisualization extends React.Component {  // Custom props you wish to be configurable in the UI must also be defined in  // the nr1.json file for the visualization. See docs for more details.  static propTypes = {    /**     * A fill color to override the default fill color. This is an example of     * a custom chart configuration.     */    fill: PropTypes.string,
    /**     * A stroke color to override the default stroke color. This is an example of     * a custom chart configuration.     */    stroke: PropTypes.string,    /**     * An array of objects consisting of a nrql `query` and `accountId`.     * This should be a standard prop for any NRQL based visualizations.     */    nrqlQueries: PropTypes.arrayOf(      PropTypes.shape({        accountId: PropTypes.number,        query: PropTypes.string,      })    ),  };
  /**   * Restructure the data for a non-time-series, facet-based NRQL query into a   * form accepted by the Recharts library's RadarChart.   * (https://recharts.org/api/RadarChart).   */  transformData = (rawData) => {    return rawData.map((entry) => ({      name: entry.metadata.name,      // Only grabbing the first data value because this is not time-series data.      value: entry.data[0].y,    }));  };
  /**   * Format the given axis tick's numeric value into a string for display.   */  formatTick = (value) => {    return value.toLocaleString();  };
  render() {    const { nrqlQueries, stroke, fill } = this.props;
    const nrqlQueryPropsAvailable =      nrqlQueries &&      nrqlQueries[0] &&      nrqlQueries[0].accountId &&      nrqlQueries[0].query;
    if (!nrqlQueryPropsAvailable) {      return <EmptyState />;    }
    return (      <AutoSizer>        {({ width, height }) => (          <NrqlQuery            query={nrqlQueries[0].query}            accountId={parseInt(nrqlQueries[0].accountId)}            pollInterval={NrqlQuery.AUTO_POLL_INTERVAL}          >            {({ data, loading, error }) => {              if (loading) {                return <Spinner />;              }
              if (error) {                return <ErrorState />;              }
              const transformedData = this.transformData(data);
              return (                <RadarChart                  width={width}                  height={height}                  data={transformedData}                >                  <PolarGrid />                  <PolarAngleAxis dataKey="name" />                  <PolarRadiusAxis tickFormatter={this.formatTick} />                  <Radar                    dataKey="value"                    stroke={stroke || '#51C9B7'}                    fill={fill || '#51C9B7'}                    fillOpacity={0.6}                  />                </RadarChart>              );            }}          </NrqlQuery>        )}      </AutoSizer>    );  }}
const EmptyState = () => (  <Card className="EmptyState">    <CardBody className="EmptyState-cardBody">      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Please provide at least one NRQL query & account ID pair      </HeadingText>      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.MEDIUM]}        type={HeadingText.TYPE.HEADING_4}      >        An example NRQL query you can try is:      </HeadingText>      <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code>    </CardBody>  </Card>);
const ErrorState = () => (  <Card className="ErrorState">    <CardBody className="ErrorState-cardBody">      <HeadingText        className="ErrorState-headingText"        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Oops! Something went wrong.      </HeadingText>    </CardBody>  </Card>);Configurer l'état de votre composant
Ajoutez l’état du composant au modèle de visualisation par défaut que nr1 a créé pour vous.
Accédez à alternate-viz/visualizations/radar-or-treemap/index.js. Vous travaillerez ici pour le reste de cette leçon.
Ajoutez une constante appelée CHART_TYPES:
import React from 'react';import PropTypes from 'prop-types';import {  Radar,  RadarChart,  PolarGrid,  PolarAngleAxis,  PolarRadiusAxis,} from 'recharts';import {  Card,  CardBody,  HeadingText,  NrqlQuery,  Spinner,  AutoSizer,} from 'nr1';
const CHART_TYPES = {  Radar: 'radar',  Treemap: 'treemap',};
export default class RadarOrTreemapVisualization extends React.Component {  // Custom props you wish to be configurable in the UI must also be defined in  // the nr1.json file for the visualization. See docs for more details.  static propTypes = {    /**     * A fill color to override the default fill color. This is an example of     * a custom chart configuration.     */    fill: PropTypes.string,
    /**     * A stroke color to override the default stroke color. This is an example of     * a custom chart configuration.     */    stroke: PropTypes.string,    /**     * An array of objects consisting of a nrql `query` and `accountId`.     * This should be a standard prop for any NRQL based visualizations.     */    nrqlQueries: PropTypes.arrayOf(      PropTypes.shape({        accountId: PropTypes.number,        query: PropTypes.string,      })    ),  };
  /**   * Restructure the data for a non-time-series, facet-based NRQL query into a   * form accepted by the Recharts library's RadarChart.   * (https://recharts.org/api/RadarChart).   */  transformData = (rawData) => {    return rawData.map((entry) => ({      name: entry.metadata.name,      // Only grabbing the first data value because this is not time-series data.      value: entry.data[0].y,    }));  };
  /**   * Format the given axis tick's numeric value into a string for display.   */  formatTick = (value) => {    return value.toLocaleString();  };
  render() {    const { nrqlQueries, stroke, fill } = this.props;
    const nrqlQueryPropsAvailable =      nrqlQueries &&      nrqlQueries[0] &&      nrqlQueries[0].accountId &&      nrqlQueries[0].query;
    if (!nrqlQueryPropsAvailable) {      return <EmptyState />;    }
    return (      <AutoSizer>        {({ width, height }) => (          <NrqlQuery            query={nrqlQueries[0].query}            accountId={parseInt(nrqlQueries[0].accountId)}            pollInterval={NrqlQuery.AUTO_POLL_INTERVAL}          >            {({ data, loading, error }) => {              if (loading) {                return <Spinner />;              }
              if (error) {                return <ErrorState />;              }
              const transformedData = this.transformData(data);
              return (                <RadarChart                  width={width}                  height={height}                  data={transformedData}                >                  <PolarGrid />                  <PolarAngleAxis dataKey="name" />                  <PolarRadiusAxis tickFormatter={this.formatTick} />                  <Radar                    dataKey="value"                    stroke={stroke || '#51C9B7'}                    fill={fill || '#51C9B7'}                    fillOpacity={0.6}                  />                </RadarChart>              );            }}          </NrqlQuery>        )}      </AutoSizer>    );  }}
const EmptyState = () => (  <Card className="EmptyState">    <CardBody className="EmptyState-cardBody">      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Please provide at least one NRQL query & account ID pair      </HeadingText>      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.MEDIUM]}        type={HeadingText.TYPE.HEADING_4}      >        An example NRQL query you can try is:      </HeadingText>      <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code>    </CardBody>  </Card>);
const ErrorState = () => (  <Card className="ErrorState">    <CardBody className="ErrorState-cardBody">      <HeadingText        className="ErrorState-headingText"        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Oops! Something went wrong.      </HeadingText>    </CardBody>  </Card>);CHART_TYPES énumère les deux types de graphiques entre lesquels vous alternerez dans votre visualisation.
Initialisez selectedChart dans state de votre composant :
import React from 'react';import PropTypes from 'prop-types';import {  Radar,  RadarChart,  PolarGrid,  PolarAngleAxis,  PolarRadiusAxis,} from 'recharts';import {  Card,  CardBody,  HeadingText,  NrqlQuery,  Spinner,  AutoSizer,} from 'nr1';
const CHART_TYPES = {  Radar: 'radar',  Treemap: 'treemap',};
export default class RadarOrTreemapVisualization extends React.Component {  // Custom props you wish to be configurable in the UI must also be defined in  // the nr1.json file for the visualization. See docs for more details.  static propTypes = {    /**     * A fill color to override the default fill color. This is an example of     * a custom chart configuration.     */    fill: PropTypes.string,
    /**     * A stroke color to override the default stroke color. This is an example of     * a custom chart configuration.     */    stroke: PropTypes.string,    /**     * An array of objects consisting of a nrql `query` and `accountId`.     * This should be a standard prop for any NRQL based visualizations.     */    nrqlQueries: PropTypes.arrayOf(      PropTypes.shape({        accountId: PropTypes.number,        query: PropTypes.string,      })    ),  };
  state = {    selectedChart: CHART_TYPES.Radar,  };
  /**   * Restructure the data for a non-time-series, facet-based NRQL query into a   * form accepted by the Recharts library's RadarChart.   * (https://recharts.org/api/RadarChart).   */  transformData = (rawData) => {    return rawData.map((entry) => ({      name: entry.metadata.name,      // Only grabbing the first data value because this is not time-series data.      value: entry.data[0].y,    }));  };
  /**   * Format the given axis tick's numeric value into a string for display.   */  formatTick = (value) => {    return value.toLocaleString();  };
  render() {    const { nrqlQueries, stroke, fill } = this.props;
    const nrqlQueryPropsAvailable =      nrqlQueries &&      nrqlQueries[0] &&      nrqlQueries[0].accountId &&      nrqlQueries[0].query;
    if (!nrqlQueryPropsAvailable) {      return <EmptyState />;    }
    return (      <AutoSizer>        {({ width, height }) => (          <NrqlQuery            query={nrqlQueries[0].query}            accountId={parseInt(nrqlQueries[0].accountId)}            pollInterval={NrqlQuery.AUTO_POLL_INTERVAL}          >            {({ data, loading, error }) => {              if (loading) {                return <Spinner />;              }
              if (error) {                return <ErrorState />;              }
              const transformedData = this.transformData(data);
              return (                <RadarChart                  width={width}                  height={height}                  data={transformedData}                >                  <PolarGrid />                  <PolarAngleAxis dataKey="name" />                  <PolarRadiusAxis tickFormatter={this.formatTick} />                  <Radar                    dataKey="value"                    stroke={stroke || '#51C9B7'}                    fill={fill || '#51C9B7'}                    fillOpacity={0.6}                  />                </RadarChart>              );            }}          </NrqlQuery>        )}      </AutoSizer>    );  }}
const EmptyState = () => (  <Card className="EmptyState">    <CardBody className="EmptyState-cardBody">      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Please provide at least one NRQL query & account ID pair      </HeadingText>      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.MEDIUM]}        type={HeadingText.TYPE.HEADING_4}      >        An example NRQL query you can try is:      </HeadingText>      <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code>    </CardBody>  </Card>);
const ErrorState = () => (  <Card className="ErrorState">    <CardBody className="ErrorState-cardBody">      <HeadingText        className="ErrorState-headingText"        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Oops! Something went wrong.      </HeadingText>    </CardBody>  </Card>);Cette valeur state stocke le type de graphique dans lequel vous souhaitez afficher vos données.
Maintenant que vous avez créé un objet qui énumère les options de type de graphique pour votre visualisation et que vous avez initialisé state.selectedChart, vous êtes prêt à implémenter une interface utilisateur de contrôle pour basculer entre les deux types de graphiques.
Ajouter SegmentedControl 
state.selectedChart n'est pas utile à moins que l'utilisateur de votre visualisation puisse réellement sélectionner un type de graphique. Utilisez SegmentedControl et SegmentedControlItem pour basculer entre les deux types de graphiques.
Importer SegmentedControl et SegmentedControlItem depuis nr1:
import React from 'react';import PropTypes from 'prop-types';import {  Radar,  RadarChart,  PolarGrid,  PolarAngleAxis,  PolarRadiusAxis,} from 'recharts';import {  AutoSizer,  Card,  CardBody,  HeadingText,  NrqlQuery,  SegmentedControl,  SegmentedControlItem,  Spinner,} from 'nr1';
const CHART_TYPES = {  Radar: 'radar',  Treemap: 'treemap',};
export default class RadarOrTreemapVisualization extends React.Component {  // Custom props you wish to be configurable in the UI must also be defined in  // the nr1.json file for the visualization. See docs for more details.  static propTypes = {    /**     * A fill color to override the default fill color. This is an example of     * a custom chart configuration.     */    fill: PropTypes.string,
    /**     * A stroke color to override the default stroke color. This is an example of     * a custom chart configuration.     */    stroke: PropTypes.string,    /**     * An array of objects consisting of a nrql `query` and `accountId`.     * This should be a standard prop for any NRQL based visualizations.     */    nrqlQueries: PropTypes.arrayOf(      PropTypes.shape({        accountId: PropTypes.number,        query: PropTypes.string,      })    ),  };
  state = {    selectedChart: CHART_TYPES.Radar,  };
  /**   * Restructure the data for a non-time-series, facet-based NRQL query into a   * form accepted by the Recharts library's RadarChart.   * (https://recharts.org/api/RadarChart).   */  transformData = (rawData) => {    return rawData.map((entry) => ({      name: entry.metadata.name,      // Only grabbing the first data value because this is not time-series data.      value: entry.data[0].y,    }));  };
  /**   * Format the given axis tick's numeric value into a string for display.   */  formatTick = (value) => {    return value.toLocaleString();  };
  render() {    const { nrqlQueries, stroke, fill } = this.props;
    const nrqlQueryPropsAvailable =      nrqlQueries &&      nrqlQueries[0] &&      nrqlQueries[0].accountId &&      nrqlQueries[0].query;
    if (!nrqlQueryPropsAvailable) {      return <EmptyState />;    }
    return (      <AutoSizer>        {({ width, height }) => (          <NrqlQuery            query={nrqlQueries[0].query}            accountId={parseInt(nrqlQueries[0].accountId)}            pollInterval={NrqlQuery.AUTO_POLL_INTERVAL}          >            {({ data, loading, error }) => {              if (loading) {                return <Spinner />;              }
              if (error) {                return <ErrorState />;              }
              const transformedData = this.transformData(data);
              return (                <RadarChart                  width={width}                  height={height}                  data={transformedData}                >                  <PolarGrid />                  <PolarAngleAxis dataKey="name" />                  <PolarRadiusAxis tickFormatter={this.formatTick} />                  <Radar                    dataKey="value"                    stroke={stroke || '#51C9B7'}                    fill={fill || '#51C9B7'}                    fillOpacity={0.6}                  />                </RadarChart>              );            }}          </NrqlQuery>        )}      </AutoSizer>    );  }}
const EmptyState = () => (  <Card className="EmptyState">    <CardBody className="EmptyState-cardBody">      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Please provide at least one NRQL query & account ID pair      </HeadingText>      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.MEDIUM]}        type={HeadingText.TYPE.HEADING_4}      >        An example NRQL query you can try is:      </HeadingText>      <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code>    </CardBody>  </Card>);
const ErrorState = () => (  <Card className="ErrorState">    <CardBody className="ErrorState-cardBody">      <HeadingText        className="ErrorState-headingText"        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Oops! Something went wrong.      </HeadingText>    </CardBody>  </Card>);Dans render(), enveloppez RadarChart dans un React.Fragment:
import React from 'react';import PropTypes from 'prop-types';import {  Radar,  RadarChart,  PolarGrid,  PolarAngleAxis,  PolarRadiusAxis,} from 'recharts';import {  AutoSizer,  Card,  CardBody,  HeadingText,  NrqlQuery,  SegmentedControl,  SegmentedControlItem,  Spinner,} from 'nr1';
const CHART_TYPES = {  Radar: 'radar',  Treemap: 'treemap',};
export default class RadarOrTreemapVisualization extends React.Component {  // Custom props you wish to be configurable in the UI must also be defined in  // the nr1.json file for the visualization. See docs for more details.  static propTypes = {    /**     * A fill color to override the default fill color. This is an example of     * a custom chart configuration.     */    fill: PropTypes.string,
    /**     * A stroke color to override the default stroke color. This is an example of     * a custom chart configuration.     */    stroke: PropTypes.string,    /**     * An array of objects consisting of a nrql `query` and `accountId`.     * This should be a standard prop for any NRQL based visualizations.     */    nrqlQueries: PropTypes.arrayOf(      PropTypes.shape({        accountId: PropTypes.number,        query: PropTypes.string,      })    ),  };
  state = {    selectedChart: CHART_TYPES.Radar,  };
  /**   * Restructure the data for a non-time-series, facet-based NRQL query into a   * form accepted by the Recharts library's RadarChart.   * (https://recharts.org/api/RadarChart).   */  transformData = (rawData) => {    return rawData.map((entry) => ({      name: entry.metadata.name,      // Only grabbing the first data value because this is not time-series data.      value: entry.data[0].y,    }));  };
  /**   * Format the given axis tick's numeric value into a string for display.   */  formatTick = (value) => {    return value.toLocaleString();  };
  render() {    const { nrqlQueries, stroke, fill } = this.props;
    const nrqlQueryPropsAvailable =      nrqlQueries &&      nrqlQueries[0] &&      nrqlQueries[0].accountId &&      nrqlQueries[0].query;
    if (!nrqlQueryPropsAvailable) {      return <EmptyState />;    }
    return (      <AutoSizer>        {({ width, height }) => (          <NrqlQuery            query={nrqlQueries[0].query}            accountId={parseInt(nrqlQueries[0].accountId)}            pollInterval={NrqlQuery.AUTO_POLL_INTERVAL}          >            {({ data, loading, error }) => {              if (loading) {                return <Spinner />;              }
              if (error) {                return <ErrorState />;              }
              const transformedData = this.transformData(data);
              return (                <React.Fragment>                  <RadarChart                    width={width}                    height={height}                    data={transformedData}                  >                    <PolarGrid />                    <PolarAngleAxis dataKey="name" />                    <PolarRadiusAxis tickFormatter={this.formatTick} />                    <Radar                      dataKey="value"                      stroke={stroke || '#51C9B7'}                      fill={fill || '#51C9B7'}                      fillOpacity={0.6}                    />                  </RadarChart>                </React.Fragment>              );            }}          </NrqlQuery>        )}      </AutoSizer>    );  }}
const EmptyState = () => (  <Card className="EmptyState">    <CardBody className="EmptyState-cardBody">      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Please provide at least one NRQL query & account ID pair      </HeadingText>      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.MEDIUM]}        type={HeadingText.TYPE.HEADING_4}      >        An example NRQL query you can try is:      </HeadingText>      <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code>    </CardBody>  </Card>);
const ErrorState = () => (  <Card className="ErrorState">    <CardBody className="ErrorState-cardBody">      <HeadingText        className="ErrorState-headingText"        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Oops! Something went wrong.      </HeadingText>    </CardBody>  </Card>);Cela vous permet de renvoyer plusieurs composants à partir du même render().
Ajoutez un SegmentedControl et deux composants SegmentedControlItem , chacun avec un value et un label:
import React from 'react';import PropTypes from 'prop-types';import {  Radar,  RadarChart,  PolarGrid,  PolarAngleAxis,  PolarRadiusAxis,} from 'recharts';import {  AutoSizer,  Card,  CardBody,  HeadingText,  NrqlQuery,  SegmentedControl,  SegmentedControlItem,  Spinner,} from 'nr1';
const CHART_TYPES = {  Radar: 'radar',  Treemap: 'treemap',};
export default class RadarOrTreemapVisualization extends React.Component {  // Custom props you wish to be configurable in the UI must also be defined in  // the nr1.json file for the visualization. See docs for more details.  static propTypes = {    /**     * A fill color to override the default fill color. This is an example of     * a custom chart configuration.     */    fill: PropTypes.string,
    /**     * A stroke color to override the default stroke color. This is an example of     * a custom chart configuration.     */    stroke: PropTypes.string,    /**     * An array of objects consisting of a nrql `query` and `accountId`.     * This should be a standard prop for any NRQL based visualizations.     */    nrqlQueries: PropTypes.arrayOf(      PropTypes.shape({        accountId: PropTypes.number,        query: PropTypes.string,      })    ),  };
  state = {    selectedChart: CHART_TYPES.Radar,  };
  /**   * Restructure the data for a non-time-series, facet-based NRQL query into a   * form accepted by the Recharts library's RadarChart.   * (https://recharts.org/api/RadarChart).   */  transformData = (rawData) => {    return rawData.map((entry) => ({      name: entry.metadata.name,      // Only grabbing the first data value because this is not time-series data.      value: entry.data[0].y,    }));  };
  /**   * Format the given axis tick's numeric value into a string for display.   */  formatTick = (value) => {    return value.toLocaleString();  };
  render() {    const { nrqlQueries, stroke, fill } = this.props;
    const nrqlQueryPropsAvailable =      nrqlQueries &&      nrqlQueries[0] &&      nrqlQueries[0].accountId &&      nrqlQueries[0].query;
    if (!nrqlQueryPropsAvailable) {      return <EmptyState />;    }
    return (      <AutoSizer>        {({ width, height }) => (          <NrqlQuery            query={nrqlQueries[0].query}            accountId={parseInt(nrqlQueries[0].accountId)}            pollInterval={NrqlQuery.AUTO_POLL_INTERVAL}          >            {({ data, loading, error }) => {              if (loading) {                return <Spinner />;              }
              if (error) {                return <ErrorState />;              }
              const transformedData = this.transformData(data);
              return (                <React.Fragment>                  <SegmentedControl                    onChange={(event, value) => console.log(value)}                  >                    <SegmentedControlItem                      value={CHART_TYPES.Radar}                      label="Radar chart"                    />                    <SegmentedControlItem                      value={CHART_TYPES.Treemap}                      label="Treemap chart"                    />                  </SegmentedControl>                  <RadarChart                    width={width}                    height={height}                    data={transformedData}                  >                    <PolarGrid />                    <PolarAngleAxis dataKey="name" />                    <PolarRadiusAxis tickFormatter={this.formatTick} />                    <Radar                      dataKey="value"                      stroke={stroke || '#51C9B7'}                      fill={fill || '#51C9B7'}                      fillOpacity={0.6}                    />                  </RadarChart>                </React.Fragment>              );            }}          </NrqlQuery>        )}      </AutoSizer>    );  }}
const EmptyState = () => (  <Card className="EmptyState">    <CardBody className="EmptyState-cardBody">      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Please provide at least one NRQL query & account ID pair      </HeadingText>      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.MEDIUM]}        type={HeadingText.TYPE.HEADING_4}      >        An example NRQL query you can try is:      </HeadingText>      <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code>    </CardBody>  </Card>);
const ErrorState = () => (  <Card className="ErrorState">    <CardBody className="ErrorState-cardBody">      <HeadingText        className="ErrorState-headingText"        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Oops! Something went wrong.      </HeadingText>    </CardBody>  </Card>);Ici, votre SegmentedControl enregistre le SegmentedControlItem.value dans la console lorsque vous modifiez votre sélection. Les valeurs que vous avez définies pour vos SegmentedControlItem composants correspondent aux deux CHART_TYPES que vous avez créés à une étape précédente.
Accédez à la racine de votre Nerdpack à alternate-viz.
Servez votre Nerdpack localement :
$nr1 nerdpack:serveOuvrez le lien vers votre visualisation qui s'affiche dans le terminal au démarrage du serveur Node :
Visualizations: ⁎  radar-or-treemap https://one.nr/012ab3cd4EfConfigurez votre visualisation avec un identifiant de compte et une requête.
Avec certaines données requises pour le traitement de votre graphique, vous voyez maintenant un RadarChart avec le SegmentedControl en haut de la vue.
Regardez la console de votre navigateur pour voir vos logs SegmentedControl .
Connectez state de votre composant au SegmentedControl 
Ajoutez une méthode pour mettre à jour state et connectez cette méthode avec le SegmentedControl que vous avez ajouté dans la dernière section.
Ajoutez une méthode de composant, appelée updateSelectedChart():
import React from 'react';import PropTypes from 'prop-types';import {  Radar,  RadarChart,  PolarGrid,  PolarAngleAxis,  PolarRadiusAxis,} from 'recharts';import {  AutoSizer,  Card,  CardBody,  HeadingText,  NrqlQuery,  SegmentedControl,  SegmentedControlItem,  Spinner,} from 'nr1';
const CHART_TYPES = {  Radar: 'radar',  Treemap: 'treemap',};
export default class RadarOrTreemapVisualization extends React.Component {  // Custom props you wish to be configurable in the UI must also be defined in  // the nr1.json file for the visualization. See docs for more details.  static propTypes = {    /**     * A fill color to override the default fill color. This is an example of     * a custom chart configuration.     */    fill: PropTypes.string,
    /**     * A stroke color to override the default stroke color. This is an example of     * a custom chart configuration.     */    stroke: PropTypes.string,    /**     * An array of objects consisting of a nrql `query` and `accountId`.     * This should be a standard prop for any NRQL based visualizations.     */    nrqlQueries: PropTypes.arrayOf(      PropTypes.shape({        accountId: PropTypes.number,        query: PropTypes.string,      })    ),  };
  state = {    selectedChart: CHART_TYPES.Radar,  };
  /**   * Restructure the data for a non-time-series, facet-based NRQL query into a   * form accepted by the Recharts library's RadarChart.   * (https://recharts.org/api/RadarChart).   */  transformData = (rawData) => {    return rawData.map((entry) => ({      name: entry.metadata.name,      // Only grabbing the first data value because this is not time-series data.      value: entry.data[0].y,    }));  };
  /**   * Format the given axis tick's numeric value into a string for display.   */  formatTick = (value) => {    return value.toLocaleString();  };
  updateSelectedChart = (evt, value) => {    this.setState({ selectedChart: value });  };
  render() {    const { nrqlQueries, stroke, fill } = this.props;
    const nrqlQueryPropsAvailable =      nrqlQueries &&      nrqlQueries[0] &&      nrqlQueries[0].accountId &&      nrqlQueries[0].query;
    if (!nrqlQueryPropsAvailable) {      return <EmptyState />;    }
    return (      <AutoSizer>        {({ width, height }) => (          <NrqlQuery            query={nrqlQueries[0].query}            accountId={parseInt(nrqlQueries[0].accountId)}            pollInterval={NrqlQuery.AUTO_POLL_INTERVAL}          >            {({ data, loading, error }) => {              if (loading) {                return <Spinner />;              }
              if (error) {                return <ErrorState />;              }
              const transformedData = this.transformData(data);
              return (                <React.Fragment>                  <SegmentedControl                    onChange={(event, value) => console.log(value)}                  >                    <SegmentedControlItem                      value={CHART_TYPES.Radar}                      label="Radar chart"                    />                    <SegmentedControlItem                      value={CHART_TYPES.Treemap}                      label="Treemap chart"                    />                  </SegmentedControl>                  <RadarChart                    width={width}                    height={height}                    data={transformedData}                  >                    <PolarGrid />                    <PolarAngleAxis dataKey="name" />                    <PolarRadiusAxis tickFormatter={this.formatTick} />                    <Radar                      dataKey="value"                      stroke={stroke || '#51C9B7'}                      fill={fill || '#51C9B7'}                      fillOpacity={0.6}                    />                  </RadarChart>                </React.Fragment>              );            }}          </NrqlQuery>        )}      </AutoSizer>    );  }}
const EmptyState = () => (  <Card className="EmptyState">    <CardBody className="EmptyState-cardBody">      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Please provide at least one NRQL query & account ID pair      </HeadingText>      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.MEDIUM]}        type={HeadingText.TYPE.HEADING_4}      >        An example NRQL query you can try is:      </HeadingText>      <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code>    </CardBody>  </Card>);
const ErrorState = () => (  <Card className="ErrorState">    <CardBody className="ErrorState-cardBody">      <HeadingText        className="ErrorState-headingText"        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Oops! Something went wrong.      </HeadingText>    </CardBody>  </Card>);Cette nouvelle méthode prend un argument value et définit state.selectedChart sur cette valeur.
Réglez SegmentedControl.onChange sur updateSelectedChart():
import React from 'react';import PropTypes from 'prop-types';import {  Radar,  RadarChart,  PolarGrid,  PolarAngleAxis,  PolarRadiusAxis,} from 'recharts';import {  AutoSizer,  Card,  CardBody,  HeadingText,  NrqlQuery,  SegmentedControl,  SegmentedControlItem,  Spinner,} from 'nr1';
const CHART_TYPES = {  Radar: 'radar',  Treemap: 'treemap',};
export default class RadarOrTreemapVisualization extends React.Component {  // Custom props you wish to be configurable in the UI must also be defined in  // the nr1.json file for the visualization. See docs for more details.  static propTypes = {    /**     * A fill color to override the default fill color. This is an example of     * a custom chart configuration.     */    fill: PropTypes.string,
    /**     * A stroke color to override the default stroke color. This is an example of     * a custom chart configuration.     */    stroke: PropTypes.string,    /**     * An array of objects consisting of a nrql `query` and `accountId`.     * This should be a standard prop for any NRQL based visualizations.     */    nrqlQueries: PropTypes.arrayOf(      PropTypes.shape({        accountId: PropTypes.number,        query: PropTypes.string,      })    ),  };
  state = {    selectedChart: CHART_TYPES.Radar,  };
  /**   * Restructure the data for a non-time-series, facet-based NRQL query into a   * form accepted by the Recharts library's RadarChart.   * (https://recharts.org/api/RadarChart).   */  transformData = (rawData) => {    return rawData.map((entry) => ({      name: entry.metadata.name,      // Only grabbing the first data value because this is not time-series data.      value: entry.data[0].y,    }));  };
  /**   * Format the given axis tick's numeric value into a string for display.   */  formatTick = (value) => {    return value.toLocaleString();  };
  updateSelectedChart = (evt, value) => {    this.setState({ selectedChart: value });  };
  render() {    const { nrqlQueries, stroke, fill } = this.props;
    const nrqlQueryPropsAvailable =      nrqlQueries &&      nrqlQueries[0] &&      nrqlQueries[0].accountId &&      nrqlQueries[0].query;
    if (!nrqlQueryPropsAvailable) {      return <EmptyState />;    }
    return (      <AutoSizer>        {({ width, height }) => (          <NrqlQuery            query={nrqlQueries[0].query}            accountId={parseInt(nrqlQueries[0].accountId)}            pollInterval={NrqlQuery.AUTO_POLL_INTERVAL}          >            {({ data, loading, error }) => {              if (loading) {                return <Spinner />;              }
              if (error) {                return <ErrorState />;              }
              const transformedData = this.transformData(data);
              return (                <React.Fragment>                  <SegmentedControl onChange={this.updateSelectedChart}>                    <SegmentedControlItem                      value={CHART_TYPES.Radar}                      label="Radar chart"                    />                    <SegmentedControlItem                      value={CHART_TYPES.Treemap}                      label="Treemap chart"                    />                  </SegmentedControl>                  <RadarChart                    width={width}                    height={height}                    data={transformedData}                  >                    <PolarGrid />                    <PolarAngleAxis dataKey="name" />                    <PolarRadiusAxis tickFormatter={this.formatTick} />                    <Radar                      dataKey="value"                      stroke={stroke || '#51C9B7'}                      fill={fill || '#51C9B7'}                      fillOpacity={0.6}                    />                  </RadarChart>                </React.Fragment>              );            }}          </NrqlQuery>        )}      </AutoSizer>    );  }}
const EmptyState = () => (  <Card className="EmptyState">    <CardBody className="EmptyState-cardBody">      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Please provide at least one NRQL query & account ID pair      </HeadingText>      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.MEDIUM]}        type={HeadingText.TYPE.HEADING_4}      >        An example NRQL query you can try is:      </HeadingText>      <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code>    </CardBody>  </Card>);
const ErrorState = () => (  <Card className="ErrorState">    <CardBody className="ErrorState-cardBody">      <HeadingText        className="ErrorState-headingText"        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Oops! Something went wrong.      </HeadingText>    </CardBody>  </Card>);Désormais, lorsque vous modifiez votre sélection dans SegmentedControl, votre sélection sera définie dans state.
Mettre en œuvre un Treemap 
Ajoutez un Treemap à votre visualisation. Cette carte sera une alternative à la RadarChart existante.
Détails techniques
Ce guide utilise des composants Recharts pour les graphiques tiers, mais vous pouvez utiliser n'importe quelle autre bibliothèque de graphiques JavaScript compatible avec la version actuelle de React lorsque vous créez des visualisations et des applications New Relic.
Importer Treemap depuis recharts:
import React from 'react';import PropTypes from 'prop-types';import {  Radar,  RadarChart,  PolarGrid,  PolarAngleAxis,  PolarRadiusAxis,  Treemap,} from 'recharts';import {  AutoSizer,  Card,  CardBody,  HeadingText,  NrqlQuery,  SegmentedControl,  SegmentedControlItem,  Spinner,} from 'nr1';
const CHART_TYPES = {  Radar: 'radar',  Treemap: 'treemap',};
export default class RadarOrTreemapVisualization extends React.Component {  // Custom props you wish to be configurable in the UI must also be defined in  // the nr1.json file for the visualization. See docs for more details.  static propTypes = {    /**     * A fill color to override the default fill color. This is an example of     * a custom chart configuration.     */    fill: PropTypes.string,
    /**     * A stroke color to override the default stroke color. This is an example of     * a custom chart configuration.     */    stroke: PropTypes.string,    /**     * An array of objects consisting of a nrql `query` and `accountId`.     * This should be a standard prop for any NRQL based visualizations.     */    nrqlQueries: PropTypes.arrayOf(      PropTypes.shape({        accountId: PropTypes.number,        query: PropTypes.string,      })    ),  };
  state = {    selectedChart: CHART_TYPES.Radar,  };
  /**   * Restructure the data for a non-time-series, facet-based NRQL query into a   * form accepted by the Recharts library's RadarChart.   * (https://recharts.org/api/RadarChart).   */  transformData = (rawData) => {    return rawData.map((entry) => ({      name: entry.metadata.name,      // Only grabbing the first data value because this is not time-series data.      value: entry.data[0].y,    }));  };
  /**   * Format the given axis tick's numeric value into a string for display.   */  formatTick = (value) => {    return value.toLocaleString();  };
  updateSelectedChart = (evt, value) => {    this.setState({ selectedChart: value });  };
  render() {    const { nrqlQueries, stroke, fill } = this.props;
    const nrqlQueryPropsAvailable =      nrqlQueries &&      nrqlQueries[0] &&      nrqlQueries[0].accountId &&      nrqlQueries[0].query;
    if (!nrqlQueryPropsAvailable) {      return <EmptyState />;    }
    return (      <AutoSizer>        {({ width, height }) => (          <NrqlQuery            query={nrqlQueries[0].query}            accountId={parseInt(nrqlQueries[0].accountId)}            pollInterval={NrqlQuery.AUTO_POLL_INTERVAL}          >            {({ data, loading, error }) => {              if (loading) {                return <Spinner />;              }
              if (error) {                return <ErrorState />;              }
              const transformedData = this.transformData(data);
              return (                <React.Fragment>                  <SegmentedControl onChange={this.updateSelectedChart}>                    <SegmentedControlItem                      value={CHART_TYPES.Radar}                      label="Radar chart"                    />                    <SegmentedControlItem                      value={CHART_TYPES.Treemap}                      label="Treemap chart"                    />                  </SegmentedControl>                  <RadarChart                    width={width}                    height={height}                    data={transformedData}                  >                    <PolarGrid />                    <PolarAngleAxis dataKey="name" />                    <PolarRadiusAxis tickFormatter={this.formatTick} />                    <Radar                      dataKey="value"                      stroke={stroke || '#51C9B7'}                      fill={fill || '#51C9B7'}                      fillOpacity={0.6}                    />                  </RadarChart>                </React.Fragment>              );            }}          </NrqlQuery>        )}      </AutoSizer>    );  }}
const EmptyState = () => (  <Card className="EmptyState">    <CardBody className="EmptyState-cardBody">      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Please provide at least one NRQL query & account ID pair      </HeadingText>      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.MEDIUM]}        type={HeadingText.TYPE.HEADING_4}      >        An example NRQL query you can try is:      </HeadingText>      <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code>    </CardBody>  </Card>);
const ErrorState = () => (  <Card className="ErrorState">    <CardBody className="ErrorState-cardBody">      <HeadingText        className="ErrorState-headingText"        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Oops! Something went wrong.      </HeadingText>    </CardBody>  </Card>);Vous pouvez désormais utiliser Treemap dans votre composant de visualisation.
Dans render(), ajoutez un composant Treemap :
import React from 'react';import PropTypes from 'prop-types';import {  Radar,  RadarChart,  PolarGrid,  PolarAngleAxis,  PolarRadiusAxis,  Treemap,} from 'recharts';import {  AutoSizer,  Card,  CardBody,  HeadingText,  NrqlQuery,  SegmentedControl,  SegmentedControlItem,  Spinner,} from 'nr1';
const CHART_TYPES = {  Radar: 'radar',  Treemap: 'treemap',};
export default class RadarOrTreemapVisualization extends React.Component {  // Custom props you wish to be configurable in the UI must also be defined in  // the nr1.json file for the visualization. See docs for more details.  static propTypes = {    /**     * A fill color to override the default fill color. This is an example of     * a custom chart configuration.     */    fill: PropTypes.string,
    /**     * A stroke color to override the default stroke color. This is an example of     * a custom chart configuration.     */    stroke: PropTypes.string,    /**     * An array of objects consisting of a nrql `query` and `accountId`.     * This should be a standard prop for any NRQL based visualizations.     */    nrqlQueries: PropTypes.arrayOf(      PropTypes.shape({        accountId: PropTypes.number,        query: PropTypes.string,      })    ),  };
  state = {    selectedChart: CHART_TYPES.Radar,  };
  /**   * Restructure the data for a non-time-series, facet-based NRQL query into a   * form accepted by the Recharts library's RadarChart.   * (https://recharts.org/api/RadarChart).   */  transformData = (rawData) => {    return rawData.map((entry) => ({      name: entry.metadata.name,      // Only grabbing the first data value because this is not time-series data.      value: entry.data[0].y,    }));  };
  /**   * Format the given axis tick's numeric value into a string for display.   */  formatTick = (value) => {    return value.toLocaleString();  };
  updateSelectedChart = (evt, value) => {    this.setState({ selectedChart: value });  };
  render() {    const { nrqlQueries, stroke, fill } = this.props;
    const nrqlQueryPropsAvailable =      nrqlQueries &&      nrqlQueries[0] &&      nrqlQueries[0].accountId &&      nrqlQueries[0].query;
    if (!nrqlQueryPropsAvailable) {      return <EmptyState />;    }
    return (      <AutoSizer>        {({ width, height }) => (          <NrqlQuery            query={nrqlQueries[0].query}            accountId={parseInt(nrqlQueries[0].accountId)}            pollInterval={NrqlQuery.AUTO_POLL_INTERVAL}          >            {({ data, loading, error }) => {              if (loading) {                return <Spinner />;              }
              if (error) {                return <ErrorState />;              }
              const transformedData = this.transformData(data);
              return (                <React.Fragment>                  <SegmentedControl onChange={this.updateSelectedChart}>                    <SegmentedControlItem                      value={CHART_TYPES.Radar}                      label="Radar chart"                    />                    <SegmentedControlItem                      value={CHART_TYPES.Treemap}                      label="Treemap chart"                    />                  </SegmentedControl>                  <RadarChart                    width={width}                    height={height}                    data={transformedData}                  >                    <PolarGrid />                    <PolarAngleAxis dataKey="name" />                    <PolarRadiusAxis tickFormatter={this.formatTick} />                    <Radar                      dataKey="value"                      stroke={stroke || '#51C9B7'}                      fill={fill || '#51C9B7'}                      fillOpacity={0.6}                    />                  </RadarChart>                  <Treemap                    width={width}                    height={height}                    data={transformedData}                    dataKey="value"                    ratio={4 / 3}                    stroke={stroke || '#000000'}                    fill={fill || '#51C9B7'}                  />                </React.Fragment>              );            }}          </NrqlQuery>        )}      </AutoSizer>    );  }}
const EmptyState = () => (  <Card className="EmptyState">    <CardBody className="EmptyState-cardBody">      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Please provide at least one NRQL query & account ID pair      </HeadingText>      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.MEDIUM]}        type={HeadingText.TYPE.HEADING_4}      >        An example NRQL query you can try is:      </HeadingText>      <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code>    </CardBody>  </Card>);
const ErrorState = () => (  <Card className="ErrorState">    <CardBody className="ErrorState-cardBody">      <HeadingText        className="ErrorState-headingText"        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Oops! Something went wrong.      </HeadingText>    </CardBody>  </Card>);Ici, vous avez défini un nouveau composant Treemap avec quelques accessoires, notamment height, width, fill et stroke.
Avec votre Nerdpack servi localement, visualisez votre visualisation. Les SegmentedControl et RadarChart sont en haut de la vue, mais si vous faites défiler vers le bas, vous verrez votre nouveau Treemap.
Basculez entre les graphiques avec vos composants state 
Utilisez state.selectedChart pour déterminer quel graphique afficher : le RadarChart ou le Treemap.
Déstructurez this.state pour accéder selectedChart en tant que constante distincte. Ensuite, comparez selectedChart à CHART_TYPES.Radar. S'ils sont identiques, affichez un RadarChart. Sinon, afficher un Treemap:
import React from 'react';import PropTypes from 'prop-types';import {  Radar,  RadarChart,  PolarGrid,  PolarAngleAxis,  PolarRadiusAxis,  Treemap,} from 'recharts';import {  AutoSizer,  Card,  CardBody,  HeadingText,  NrqlQuery,  SegmentedControl,  SegmentedControlItem,  Spinner,} from 'nr1';
const CHART_TYPES = {  Radar: 'radar',  Treemap: 'treemap',};
export default class RadarOrTreemapVisualization extends React.Component {  // Custom props you wish to be configurable in the UI must also be defined in  // the nr1.json file for the visualization. See docs for more details.  static propTypes = {    /**     * A fill color to override the default fill color. This is an example of     * a custom chart configuration.     */    fill: PropTypes.string,
    /**     * A stroke color to override the default stroke color. This is an example of     * a custom chart configuration.     */    stroke: PropTypes.string,    /**     * An array of objects consisting of a nrql `query` and `accountId`.     * This should be a standard prop for any NRQL based visualizations.     */    nrqlQueries: PropTypes.arrayOf(      PropTypes.shape({        accountId: PropTypes.number,        query: PropTypes.string,      })    ),  };
  state = {    selectedChart: CHART_TYPES.Radar,  };
  /**   * Restructure the data for a non-time-series, facet-based NRQL query into a   * form accepted by the Recharts library's RadarChart.   * (https://recharts.org/api/RadarChart).   */  transformData = (rawData) => {    return rawData.map((entry) => ({      name: entry.metadata.name,      // Only grabbing the first data value because this is not time-series data.      value: entry.data[0].y,    }));  };
  /**   * Format the given axis tick's numeric value into a string for display.   */  formatTick = (value) => {    return value.toLocaleString();  };
  updateSelectedChart = (evt, value) => {    this.setState({ selectedChart: value });  };
  render() {    const { nrqlQueries, stroke, fill } = this.props;    const { selectedChart } = this.state;
    const nrqlQueryPropsAvailable =      nrqlQueries &&      nrqlQueries[0] &&      nrqlQueries[0].accountId &&      nrqlQueries[0].query;
    if (!nrqlQueryPropsAvailable) {      return <EmptyState />;    }
    return (      <AutoSizer>        {({ width, height }) => (          <NrqlQuery            query={nrqlQueries[0].query}            accountId={parseInt(nrqlQueries[0].accountId)}            pollInterval={NrqlQuery.AUTO_POLL_INTERVAL}          >            {({ data, loading, error }) => {              if (loading) {                return <Spinner />;              }
              if (error) {                return <ErrorState />;              }
              const transformedData = this.transformData(data);
              return (                <React.Fragment>                  <SegmentedControl onChange={this.updateSelectedChart}>                    <SegmentedControlItem                      value={CHART_TYPES.Radar}                      label="Radar chart"                    />                    <SegmentedControlItem                      value={CHART_TYPES.Treemap}                      label="Treemap chart"                    />                  </SegmentedControl>                  {selectedChart === CHART_TYPES.Radar ? (                    <RadarChart                      width={width}                      height={height}                      data={transformedData}                    >                      <PolarGrid />                      <PolarAngleAxis dataKey="name" />                      <PolarRadiusAxis tickFormatter={this.formatTick} />                      <Radar                        dataKey="value"                        stroke={stroke || '#51C9B7'}                        fill={fill || '#51C9B7'}                        fillOpacity={0.6}                      />                    </RadarChart>                  ) : (                    <Treemap                      width={width}                      height={height}                      data={transformedData}                      dataKey="value"                      ratio={4 / 3}                      stroke={stroke || '#000000'}                      fill={fill || '#51C9B7'}                    />                  )}                </React.Fragment>              );            }}          </NrqlQuery>        )}      </AutoSizer>    );  }}
const EmptyState = () => (  <Card className="EmptyState">    <CardBody className="EmptyState-cardBody">      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Please provide at least one NRQL query & account ID pair      </HeadingText>      <HeadingText        spacingType={[HeadingText.SPACING_TYPE.MEDIUM]}        type={HeadingText.TYPE.HEADING_4}      >        An example NRQL query you can try is:      </HeadingText>      <code>FROM NrUsage SELECT sum(usage) FACET metric SINCE 1 week ago</code>    </CardBody>  </Card>);
const ErrorState = () => (  <Card className="ErrorState">    <CardBody className="ErrorState-cardBody">      <HeadingText        className="ErrorState-headingText"        spacingType={[HeadingText.SPACING_TYPE.LARGE]}        type={HeadingText.TYPE.HEADING_3}      >        Oops! Something went wrong.      </HeadingText>    </CardBody>  </Card>);Ici, vous avez utilisé une expression ternaire pour restituer un RadarChart ou un Treemap. Le graphique rendu est déterminé par la valeur de selectedChart.
Avec votre Nerdpack servi localement, visualisez votre visualisation.
Sélectionnez Radar chart dans le SegmentedControl.
Sélectionnez Treemap chart dans le SegmentedControl.
Résumé
Félicitations! Dans cette leçon, vous avez appris à :
- Personnalisez votre visualisation à l'aide des composants du SDK New Relic One
 - Ajoutez un nouveau type de graphique à votre visualisation
 - Créez une interaction utilisateur dans votre visualisation
 
Conseil
Cette leçon fait partie d'un cours qui vous apprend à créer une visualisation personnalisée sur la plateforme New Relic. Lorsque vous êtes prêt, passez à la leçon suivante : Personnaliser les visualisations avec la configuration.