通常我会确保为我的问题包含一个代码示例,但是在这种情况下,我的代码与the following D3 Radio Button example 100%相似,我只是想将其包含在我的反应组件中。
示例中的相关代码是点击处理程序:
.on("click",function(d,i) {
updateButtonColors(d3.select(this), d3.select(this.parentNode))
d3.select("#numberToggle").text(i+1)
});
然而,我没有切换数字,而是在点击此单选按钮时尝试更改我的反应应用的状态。现在,假设我只是试图将状态设置为1,2或3之一,那样(i + 1)就是我想要设置的状态。< / p>
我尝试直接在点击处理程序中调用setState(),但是我的状态没有改变。有关如何做到这一点的任何想法?如果我需要更多代码,请告诉我。
编辑:我已经尝试添加到目前为止我所拥有的代码片段,但我很难让它在stackoverflow上运行。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
chartType: 1
}
}
drawChartTypeButton() {
// colors for different button states
const defaultColor= "#7777BB"
const hoverColor= "#0000ff"
const pressedColor= "#000077"
const bWidth= 8; //button width
const bHeight= 5; //button height
const bSpace= 1; //space between buttons
const x0 = 5; //x offset
const y0 = 5; //y offset
const labels = [1, 2, 3];
const updateButtonColors = function(button, parent) {
parent.selectAll("rect")
.attr("fill",defaultColor)
button.select("rect")
.attr("fill",pressedColor)
}
// groups for each button (which will hold a rect and text)
const chartTypeButton = d3.select('g.allbuttons')
const buttonGroups= chartTypeButton.selectAll("g.button")
.data(labels)
.enter()
.append("g")
.attr("class", "button")
.style("cursor", "pointer")
.on("click", function(d,i) {
updateButtonColors(d3.select(this), d3.select(this.parentNode))
this.setState({chartType: 2})
})
.on("mouseover", function() {
if (d3.select(this).select("rect").attr("fill") != pressedColor) {
d3.select(this)
.select("rect")
.attr("fill",hoverColor);
}
})
.on("mouseout", function() {
if (d3.select(this).select("rect").attr("fill") != pressedColor) {
d3.select(this)
.select("rect")
.attr("fill",defaultColor);
}
})
buttonGroups.append("rect")
.attr("class","buttonRect")
.attr("width",bWidth)
.attr("height",bHeight)
.attr("x", function(d,i) {return x0+(bWidth+bSpace)*i;})
.attr("y",y0)
.attr("rx",1) //rx and ry give the buttons rounded corners
.attr("ry",1)
.attr("fill",defaultColor)
// adding text to each toggle button group, centered
// within the toggle button rect
buttonGroups.append("text")
.attr("class","buttonText")
.attr("font-family", "arial")
.attr("font-size", "0.1em")
.attr("x",function(d,i) {
return x0 + (bWidth+bSpace)*i + bWidth/2;
})
.attr("y",y0)
.attr("text-anchor","middle")
.attr("dominant-baseline","central")
.attr("fill","black")
.text(function(d) {return d;})
}
componentDidMount() {
const chart = d3.select('.chart')
.attr('width', 320)
.attr('height', 240)
.attr("viewBox", "0, 0, " + 50 + ", " + 50 + "")
this.drawChartTypeButton();
}
render() {
return(
<div className='container'>
<svg className='chart'>
<g className="allbuttons" />
</svg>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id='root'>
Damnit Work
</div>
答案 0 :(得分:1)
您似乎混淆了点击处理程序中的this
范围,您对d3选择器使用this作为反应组件。
通常我们可以使用箭头函数保留this
范围,但是你似乎还需要d3,只需创建一个保存当前上下文的局部变量,这样你就可以在你的点击函数中重复使用它/ p>
// create a local reference to "this" in the drawCharTypeButton function
const self = this;
// use the local reference to update the componenents state
.on("click", function(d,i) {
updateButtonColors(d3.select(this), d3.select(this.parentNode));
self.setState({chartType: 2});
})
然后您当前的代码将正常工作(如果它只显示3个按钮,则选择3个中的任何一个)
请注意,在您的示例代码中,chartWidth
和chartHeight
变量未定义,因此我将它们设置为320x240,因此它与SO上的渲染空间匹配一点
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
chartType: 1
}
}
drawChartTypeButton() {
// colors for different button states
const defaultColor= "#7777BB"
const hoverColor= "#0000ff"
const pressedColor= "#000077"
const bWidth= 8; //button width
const bHeight= 6; //button height
const bSpace= 0.5; //space between buttons
const x0 = 5; //x offset
const y0 = 14; //y offset
const labels = [1, 2, 3];
const updateButtonColors = function(button, parent) {
parent.selectAll("rect")
.attr("fill",defaultColor)
button.select("rect")
.attr("fill",pressedColor)
}
// groups for each button (which will hold a rect and text)
const self = this;
const chartTypeButton = d3.select('g.allbuttons')
const buttonGroups= chartTypeButton.selectAll("g.button")
.data(labels)
.enter()
.append("g")
.attr("class", "button")
.style("cursor", "pointer")
.on("click", function(d,i) {
updateButtonColors(d3.select(this), d3.select(this.parentNode))
self.setState({chartType: 2})
})
.on("mouseover", function() {
if (d3.select(this).select("rect").attr("fill") != pressedColor) {
d3.select(this)
.select("rect")
.attr("fill",hoverColor);
}
})
.on("mouseout", function() {
if (d3.select(this).select("rect").attr("fill") != pressedColor) {
d3.select(this)
.select("rect")
.attr("fill",defaultColor);
}
})
buttonGroups.append("rect")
.attr("class","buttonRect")
.attr("width",bWidth)
.attr("height",bHeight)
.attr("x", function(d,i) {return x0+(bWidth+bSpace)*i;})
.attr("y",y0)
.attr("rx",5) //rx and ry give the buttons rounded corners
.attr("ry",5)
.attr("fill",defaultColor)
// adding text to each toggle button group, centered
// within the toggle button rect
buttonGroups.append("text")
.attr("class","buttonText")
.attr("font-family", "arial")
.attr("font-size", "0.1em")
.attr("x",function(d,i) {
return x0 + (bWidth+bSpace)*i + bWidth/2;
})
.attr("y",y0+bHeight/2)
.attr("text-anchor","middle")
.attr("dominant-baseline","central")
.attr("fill","white")
.text(function(d) {return d;})
}
componentDidMount() {
const chart = d3.select('.chart')
.attr('width', 160)
.attr('height', 120)
.attr("viewBox", "0, 0, " + 50 + ", " + 50 + "")
this.drawChartTypeButton();
}
render() {
return(
<div className='container'>
<svg className='chart'>
<g className="allbuttons" />
</svg>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id='root'>
Damnit Work
</div>
&#13;
关于d3,react组合的最佳实践,你应该尝试在react内进行所有DOM操作。
现在找到一个可能不完全可能的图表,但这3个按钮可以很容易地呈现而不需要d3
我还没有合并这些渲染引擎,所以我不能说你当前的方法是否有缺点