Reputation: 994
I am writing code in react.js combining with d3.js. But there is a small, but something I don't understand its behaviour..
componentWillMount() {
this.setState({
dummyData: [{
price: 13,
age: 43,
etc: 99
},
{
price: 33,
age: 22,
etc: 100
}]
}
componentDidMount () {
this.keys = Object.keys(this.state.dummyData[0]);
console.log(this.keys) // ["price", "age", "etc"]
}
someMethod(){
console.log(this.keys) // ["price", "age", "etc"]
this.svg.append('g')
.selectAll('g')
.data(this.state.dummyData)
.enter()
.append('g')
.attr('transform', d => {
console.log(this.keys); // ["price", "age", "etc"]
return 'translate(' + this.x0(d.name) + ', 0)';
})
.selectAll('rect')
.data( function(d){
console.log(this.keys); // undefined
return this.keys.map( function(key){ return { key: key, value: d[key] }; }); }) // This statement causes an error
.enter()
.append('rect')
.attr('x', function(d){ return this.x1(d.key) })
.attr('y', function(d){ return this.y(d.value) })
.attr('width', this.x1.bandwidth())
.attr('height', function(d){ return height - this.y(d.value) })
.attr('fill', function(d){ return this.z(d.key) });
}
...
As you can see from the code, this.keys remains its value until it reaches second data call. I really don't get what happens at that point.
Upvotes: 0
Views: 23
Reputation: 1162
That's because of how scope and functions work in javascript. If you change your function to an arrow function it will automatically bind the scope and you will see what you expect.
As a quick explanation: Arrow functions autobind the scope where they are declared while functions don't so you have to explicitly bind the scope you want to the function.
Upvotes: 1