Nivo条形图调用标签函数数百次
Nivo bar chart calling label function hundreds of times
我正在使用 Nivo 条来表示用户的预算进度。我通过将类别平衡除以类别目标来标准化数据。示例数据。
[{
"category": "Gas",
"budget": 0.24,
"over_budget": 0.0
},
{
"category": "Groceries",
"budget": 1.0,
"over_budget": 0.26
}]
我不想将这些值用作图表上的标签。我打算使用实际余额值作为标签。我有一个端点,它将 return 一个类别的余额,并尝试通过以下方式使用该值:
<ResponsiveBar
...
label={d => this.getDollarAmount(d.value)}
...
>
函数POC为:
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;
发生多次调用是因为条形图正在为每个动画 tick/frame 渲染调用 label
函数。如果我们设置一个计数器,我们会看到 animate
属性设置为 true
它将渲染 450+
到 550+
次,但是如果我们设置属性 animate
到 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。我已将 animate
设置为 false
并且 getDollarAmount
中的 counter
日志调用 6
次。尝试将 animate
更改为 true
,您将看到 500+-
渲染。
此外,您不必为每个 label
调用都创建一个函数,您可以只传递 getDollarAmount
函数并让它处理整个 d
参数,就像这样:
getDollarAmount(d) {
// Remove every console.log inside this function
return `$${d.value}`
}
render() {
return (
<ResponsiveBar
animate={false}
label={this.getDollarAmount}
...
);
}
我正在使用 Nivo 条来表示用户的预算进度。我通过将类别平衡除以类别目标来标准化数据。示例数据。
[{
"category": "Gas",
"budget": 0.24,
"over_budget": 0.0
},
{
"category": "Groceries",
"budget": 1.0,
"over_budget": 0.26
}]
我不想将这些值用作图表上的标签。我打算使用实际余额值作为标签。我有一个端点,它将 return 一个类别的余额,并尝试通过以下方式使用该值:
<ResponsiveBar
...
label={d => this.getDollarAmount(d.value)}
...
>
函数POC为:
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;
发生多次调用是因为条形图正在为每个动画 tick/frame 渲染调用 label
函数。如果我们设置一个计数器,我们会看到 animate
属性设置为 true
它将渲染 450+
到 550+
次,但是如果我们设置属性 animate
到 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。我已将 animate
设置为 false
并且 getDollarAmount
中的 counter
日志调用 6
次。尝试将 animate
更改为 true
,您将看到 500+-
渲染。
此外,您不必为每个 label
调用都创建一个函数,您可以只传递 getDollarAmount
函数并让它处理整个 d
参数,就像这样:
getDollarAmount(d) {
// Remove every console.log inside this function
return `$${d.value}`
}
render() {
return (
<ResponsiveBar
animate={false}
label={this.getDollarAmount}
...
);
}