reactjs - 使用 d3.csv 加载数据后无法更新 React 中的状态
问题描述
我正在使用 React 使用 D3v4 构建力模拟。但是,如果我的对象数组已经处于我的状态(在本例中为节点),并且如果我尝试从 csv 文件中读取它并使用 setState 它不起作用,我只能让它工作。同样在我的 Force.js 文件中,当我尝试为 ForceX 设置 this.props.width / 2 为 ForceY 设置 this.props.height / 2 时它不起作用,我必须直接为 ForceX 输入 400 ForceY 需要 250 美元才能正常工作。
如果有人能指出我正确的方向,那就太好了!
不使用 d3.csv 的版本:
应用程序.js
import React, { Component } from "react";
import * as d3 from "d3";
import Force from "./Force";
class App extends Component {
state = {
width: 800,
height: 500,
nodes: [
{
"ID": 1,
"name": "Chlamydoselachus africana",
"url": "https://en.wikipedia.org/wiki/Chlamydoselachus_africana",
"common_name": "African frilled shark",
"size": 117,
"family": "Chlamydoselachidae",
"family_common": "Frilled Sharks",
"min_depth": 300,
"max_depth": 1400,
"IUCN": "NA",
"CITES": 0,
"baum": "",
"family_grouped": "Frilled Sharks"
},
{
"ID": 2,
"name": "Chlamydoselachus anguineus",
"url": "https://en.wikipedia.org/wiki/Chlamydoselachus_anguineus",
"common_name": "Frilled shark",
"size": 150,
"family": "Chlamydoselachidae",
"family_common": "Frilled Sharks",
"min_depth": 0,
"max_depth": 1570,
"IUCN": "LC",
"CITES": 0,
"baum": "",
"family_grouped": "Frilled Sharks"
},
{
"ID": 3,
"name": "Heptranchias perlo",
"url": "https://en.wikipedia.org/wiki/Heptranchias_perlo",
"common_name": "Sharp-nose sevengill shark",
"size": 140,
"family": "Hexanchidae",
"family_common": "Cow Sharks",
"min_depth": 0,
"max_depth": 1000,
"IUCN": "NT",
"CITES": 0,
"baum": "",
"family_grouped": "Cow Sharks"
},
{
"ID": 4,
"name": "Hexanchus griseus",
"url": "https://en.wikipedia.org/wiki/Hexanchus_griseus",
"common_name": "Blunt-nose sixgill shark",
"size": 790,
"family": "Hexanchidae",
"family_common": "Cow Sharks"
},
{
"ID": 5,
"name": "Hexanchus nakamurai",
"url": "https://en.wikipedia.org/wiki/Hexanchus_nakamurai",
"common_name": "Bigeyed sixgill shark",
"size": 180,
"family": "Hexanchidae",
"family_common": "Cow Sharks"
},
{
"ID": 6,
"name": "Hexanchus vitulus",
"url": "https://en.wikipedia.org/wiki/Hexanchus_vitulus",
"common_name": "Atlantic sixgill shark",
"size": 220,
"family": "Hexanchidae",
"family_common": "Cow Sharks"
},
{
"ID": 7,
"name": "Notorynchus cepedianus",
"url": "https://en.wikipedia.org/wiki/Notorynchus_cepedianus",
"common_name": "Broad-nose sevengill shark",
"size": 300,
"family": "Hexanchidae",
"family_common": "Cow Sharks"
},
{
"ID": 8,
"name": "Centrophorus atromarginatus",
"url": "https://en.wikipedia.org/wiki/Centrophorus_atromarginatus",
"common_name": "Dwarf gulper shark",
"size": 87,
"family": "Centrophoridae",
"family_common": "Gulper Sharks"
},
{
"ID": 9,
"name": "Centrophorus granulosus",
"url": "https://en.wikipedia.org/wiki/Centrophorus_granulosus",
"common_name": "Gulper shark",
"size": 100,
"family": "Centrophoridae",
"family_common": "Gulper Sharks"
},
{
"ID": 10,
"name": "Centrophorus harrissoni",
"url": "https://en.wikipedia.org/wiki/Centrophorus_harrissoni",
"common_name": "Dumb gulper shark",
"size": 110,
"family": "Centrophoridae",
"family_common": "Gulper Sharks"
},
{
"ID": 11,
"name": "Centrophorus moluccensis",
"url": "https://en.wikipedia.org/wiki/Centrophorus_moluccensis",
"common_name": "Small-fin gulper shark",
"size": 98,
"family": "Centrophoridae",
"family_common": "Gulper Sharks"
},
{
"ID": 12,
"name": "Centrophorus seychellorum",
"url": "https://en.wikipedia.org/wiki/Centrophorus_seychellorum",
"common_name": "Seychelles gulper shark",
"size": 80,
"family": "Centrophoridae",
"family_common": "Gulper Sharks"
},
{
"ID": 13,
"name": "Centrophorus squamosus",
"url": "https://en.wikipedia.org/wiki/Centrophorus_squamosus",
"common_name": "Leaf-scale gulper shark",
"size": 158,
"family": "Centrophoridae",
"family_common": "Gulper Sharks"
},
{
"ID": 14,
"name": "Centrophorus tessellatus",
"url": "https://en.wikipedia.org/wiki/Centrophorus_tessellatus",
"common_name": "Mosaic gulper shark",
"size": 89,
"family": "Centrophoridae",
"family_common": "Gulper Sharks"
},
{
"ID": 15,
"name": "Centrophorus uyato",
"url": "https://en.wikipedia.org/wiki/Centrophorus_uyato",
"common_name": "Little gulper shark",
"size": 110,
"family": "Centrophoridae",
"family_common": "Gulper Sharks"
}],
margin:{left:10,top:10,right:10,bottom:10}
};
render() {
return (
<Force width={this.state.width} height={this.state.height} data={this.state.nodes} />
);
}
}
export default App;
Force.js
import React from "react";
import * as d3 from "d3";
import _ from "lodash";
class Force extends React.Component {
constructor(props){
super(props);
var forceSim;
}
componentDidMount() {
var radiusScale = d3.scaleSqrt()
.range([0,0.7]);
this.forceSim = d3.forceSimulation(this.props.data)
.force('x', d3.forceX(function(d) {
return 400
}).strength(0.03))
.force('y', d3.forceY(function(d) {
return 250
}).strength((0.03)))
.force('collide', d3.forceCollide(function(d) {
return radiusScale(+d.size)
})).velocityDecay(0.1).alphaDecay(0.01);
this.forceSim.on('tick', () => this.setState({nodes: this.props.data}));
}
componentWillUnmount() {
this.forceSim.stop();
}
render() {
var colorScale = d3.scaleOrdinal()
.range(['#450303', '#6e0505', '#951f1f'
]);
var radiusScale = d3.scaleSqrt()
.range([0.5,0.9]);
return (
<svg width={this.props.width} height={this.props.height}>
{this.props.data.map((node, index) =>(
<circle r={radiusScale(node.size)} cx={node.x} cy={node.y} fill={colorScale(node.family)} key={index}/>
))}
</svg>
);
}
}
export default Force;
使用 d3.csv 不起作用的版本,但我想让它工作:
应用程序.js
import React, { Component } from "react";
import * as d3 from "d3";
import Force from "./Force";
import data from './data.csv';
class App extends Component {
state = {
width: 800,
height: 500,
nodes: [],
margin:{left:10,top:10,right:10,bottom:10}
};
componentDidMount() {
d3.csv(data).then(function(data) {
console.log(data)
this.setState(prevState =>({
nodes: data
}))
}).catch(function(err) {
throw err;
})
}
render() {
return (
<Force width={this.state.width} height={this.state.height} data={this.state.nodes} />
);
}
}
export default App;
Force.js
this.forceSim = d3.forceSimulation(this.props.data)
.force('x', d3.forceX(function(d) {
return (this.props.width)/2 ////HERE
}).strength(0.03))
.force('y', d3.forceY(function(d) {
return (this.props.height)/2 ////HERE
}).strength((0.03)))
.force('collide', d3.forceCollide(function(d) {
return radiusScale(+d.size)
})).velocityDecay(0.1).alphaDecay(0.01);
这是 csv 文件数据:
ID,name,url,common_name,size,family,family_common 1,Chlamydoselachusafricana, https://en.wikipedia.org/wiki/Chlamydoselachus_africana,African frilled Shark ,117,Chlamydoselachidae,Frilled Sharks 2,Chlamydoselachus anguineus, https:// /en.wikipedia.org/wiki/Chlamydoselachus_anguineus ,褶边鲨,150,Chlamydoselachidae,褶边鲨 3,Heptranchias perlo, https://en.wikipedia.org/wiki/Heptranchias_perlo ,尖鼻七鳃鲨,140,Hexanchidae,牛鲨鱼 4,Hexanchus griseus,https: //en.wikipedia.org/wiki/Hexanchus_griseus,钝鼻六鳃鲨,790,Hexanchidae,牛鲨 5,Hexanchus nakamurai,https ://en.wikipedia.org/wiki/Hexanchus_nakamurai ,大眼六鳃鲨,180,Hexanchidae,Cow Sharks 6,Hexanchus vitulus,https://en.wikipedia.org/wiki/Hexanchus_vitulus ,大西洋六鳃鲨,220,六鳃鲨科,牛鲨 7,Notorynchus cepedianus, https://en.wikipedia.org/wiki/Notorynchus_cepedianus ,宽鼻七鳃鲨,300 ,Hexanchidae,Cow Sharks 8,Centrophorus atromarginatus, https://en.wikipedia.org/wiki/Centrophorus_atromarginatus ,侏儒鲨,87,Centrophoridae,Gulper Sharks 9,Centrophorus granulosus, https://en.wikipedia.org/wiki /Centrophorus_granulosus, Gulper Sharks,100,Centrophoridae,Gulper Sharks 10,Centrophorus harrissoni, https://en.wikipedia.org/wiki/Centrophorus_harrissoni,Dumb gulper Shark,110,Centrophoridae,Gulper Sharks 11,Centrophorus moluccensis,https://en.wikipedia.org/wiki/Centrophorus_moluccensis,Small-fin gulper shark,98,Centrophoridae,Gulper Sharks 12,Centrophorus seychhellorum, https://en.wikipedia.org/wiki/Centrophorus_seychhellorum,Seychelles gulper Sharks ,80 ,Centrophoridae,Gulper Sharks 13,Centrophorus squamosus, https://en.wikipedia.org/wiki/Centrophorus_squamosus ,叶鳞鲨,158,Centrophoridae,Gulper Sharks 14,Centrophorus tessellatus, https://en.wikipedia.org /wiki/Centrophorus_tessellatus,Mosaic gulper shark,89,Centrophoridae,Gulper Sharks
解决方案
错误在于匿名函数和this
. 这是对工作原理的很好解释this
:https ://stackoverflow.com/a/3127440/5122581
在您的代码中:
d3.csv(data).then(function(data) {
console.log(data)
this.setState(prevState =>({
nodes: data
}))
}).catch(function(err) {
throw err;
})
您使用匿名函数将 promise 传递给 then 回调。此函数没有this
您期望的 -binding。有三种解决方案:
箭头功能:
d3.cvs(data).then((data) => {
this.setState({ nodes: data });
});
this
在外部范围内创建变量:
const self = this;
d3.cvs(data).then(function(data) {
self.setState({ nodes: data });
});
绑定函数:
function callback(data) {
this.setState({ nodes: data });
}
d3.csv(data).then(callback.bind(this));
由于您已经在使用箭头函数,我认为它们是最简洁和优雅的解决方案
推荐阅读
- python - 原始异常文本为:“RelatedManager”对象没有属性“类型”。- 姜戈休息
- python - 正则表达式:找到有限的迭代
- c++ - 无法在 INT FUNCTION C++ 中返回值
- javascript - PHP中的301永久重定向
- python - Python:在 txt 文件中写入附加文本
- postgresql - 将卷从 linux 容器挂载到 windows 容器
- function - 为什么在kotlin中任何子类实例的equals函数返回布尔值?
- reactjs - 通过链接地址导航到反应应用程序中的特定位置?
- flutter - Flutter 传递的参数总是返回 null
- python - 对 dicts 使用 bot 命令