代码之家  ›  专栏  ›  技术社区  ›  brewcrazy

Nivo条形图调用标签函数一百次

  •  0
  • brewcrazy  · 技术社区  · 4 年前

    我使用Nivo bar来表示用户在预算上的进度。我通过将类别平衡除以类别目标来规范化数据。示例数据。

    [{
        "category": "Gas",
        "budget": 0.24,
        "over_budget": 0.0
    },
    {
        "category": "Groceries",
        "budget": 1.0,
        "over_budget": 0.26
    }]
    

    我不希望这些值用作图表上的标签。我打算用实际余额作为标签。我有一个终结点将返回类别的余额,并已尝试以下操作来使用该值:

    <ResponsiveBar
    ...
    label={d => this.getDollarAmount(d.value)}
    ...
    >
    

    getDollarAmount(value) {
        console.log("hitting getDollarAmount")
        return 1
      };
    

    日志消息被记录500多次。我的期望是函数在图表中的每一条中只被击中一次。

    编辑-下面是整个条形图组件:

    import axios from 'axios';
    
    import React, { Component } from "react";
    
    import { ResponsiveBar } from '@nivo/bar'
    
    // Nivo theming
    const theme = {
      axis: {
        ticks: {
          line: {
            stroke: "#e9ecee",
            strokeWidth: 40
          },
          text: {
            // fill: "#919eab",
            fill: "black",
            fontFamily: "BlinkMacSystemFont",
            fontSize: 16
          }
        }
      },
      grid: {
        line: {
          stroke: "#e9ecee",
          strokeWidth: 5
        }
      },
      legends: {
        text: {
          fontFamily: "BlinkMacSystemFont"
        }
      }
    };
    
    let budgetStatusAPI = 'http://127.0.0.1:8000/api/budget_status/?auth_user=1&month=2020-02-01';
    
    class BarChart extends Component {
    
      constructor(props) {
        super(props);
    
        this.state = {
          data: [],
        }
    
        this.getDollarAmount = this.getDollarAmount.bind(this);
      }
    
    
      componentDidMount() {
        console.log("component did mount")
    
        axios.get(budgetStatusAPI).then(response => {
          this.setState({
            data: response.data
          }, function () {
            console.log(this.state.data);
          })
        });
      }
    
      componentDidUpdate() {
        console.log("component did update")
      }
    
      getDollarAmount(value) {
        console.log("hitting getDollarAmount")
        console.log(value)
        return 1
      };
    
    
      render() {
    
        const hard_data = [
            {
              "category": "Groceries",
              "budget_status": 1.0,
              "over_budget": .26,
            },
            {
              "category": "Gas",
              "budget_status": .24,
              "over_budget": 0.0,
            }]
    
        return(
    
          <ResponsiveBar
            maxValue={1.5}
            markers={[
                {
                    axis: 'x',
                    value: 1,
                    lineStyle: { stroke: 'rgba(0, 0, 0, .35)', strokeWidth: 2 },
                    legend: 'Goal',
                    legendOrientation: 'horizontal',
                    legendPosition: 'top'
                },
            ]}
            enableGridX={false}
            gridXValues={[1]}
            enableGridY={false}
            data={this.state.data}
            // data={hard_data}
            keys={['budget_status', 'over_budget']}
            indexBy="category"
            margin={{ top: 25, right: 130, bottom: 50, left: 125 }}
            padding={0.3}
            layout="horizontal"
            colors={{ scheme: 'set2' }}
            theme={theme}
            defs={[
                {
                    id: 'dots',
                    type: 'patternDots',
                    background: 'inherit',
                    color: '#38bcb2',
                    size: 4,
                    padding: 1,
                    stagger: true
                },
                {
                    id: 'lines',
                    type: 'patternLines',
                    background: 'inherit',
                    color: '#eed312',
                    rotation: -45,
                    lineWidth: 6,
                    spacing: 10
                }
            ]}
            borderColor={{ from: 'color', modifiers: [ [ 'darker', 1.6 ] ] }}
            axisBottom={null}
            label={d => this.getDollarAmount(d.value)}
            isInteractive={false}
            animate={true}
            motionStiffness={90}
            motionDamping={15}
        />
        )
      }
    }
    
    
    export default BarChart;
    

    在此转载: https://codesandbox.io/s/nivo-bar-label-issue-k4qek

    0 回复  |  直到 4 年前
        1
  •  0
  •   Christos Lytras    4 年前

    多重调用正在发生,因为条形图正在调用 label 每个动画滴答/帧渲染的函数。如果我们设置一个柜台,我们就可以看到 animate true 它将从 450+ 550+ 几次,但如果我们设置道具 使有生气 false ,我们将呈现 6 > 0.0 .

    如果要避免所有这些渲染,则必须使用 animate={false} 像这样的道具:

    getDollarAmount(value) {
      // Remove every console.log inside this function
    
      return `$${value}`
    }
    
    render() {
      return (
        <ResponsiveBar
          animate={false}
          label={d => this.getDollarAmount(d.value)}
          ...
      );
    }
    

    CodeSandbox . 我已经准备好了 使有生气 以及 counter 登录内部 getDollarAmount 正在呼叫 6个 使有生气 真的 你会看到 500+-

    而且,您不必为每个 标签 getDollarAmount公司 d 参数如下:

    getDollarAmount(d) {
      // Remove every console.log inside this function
    
      return `$${d.value}`
    }
    
    render() {
      return (
        <ResponsiveBar
          animate={false}
          label={this.getDollarAmount}
          ...
      );
    }