I'm trying to modify my code to load a Json file from an URL rather than to use from a local file. Can anyone please explain me how to resolve this issue
const TAXONOMY_DATA = require(../../assets/chord.json);
//for filters**
class AddRemoveSelection extends Component {
constructor(props) {
super(props);
this.state = {
selectedOptions: []
}
}
handleDeselect = (deselectedOptions) => {
var selectedOptions = this.state.selectedOptions.slice()
deselectedOptions.forEach(option => {
selectedOptions.splice(selectedOptions.indexOf(option), 1)
})
this.setState({ selectedOptions })
this.props.onChange(selectedOptions)
}
handleSelect = (selectedOptions) => {
selectedOptions.sort((a, b) => a.id - b.id)
this.setState({ selectedOptions })
this.props.onChange(selectedOptions)
}
componentWillReceiveProps(nextProps) {
if (nextProps.options !== this.props.options) {
this.setState({ selectedOptions: nextProps.options });
}
}
render() {
const { selectedOptions } = this.state
const { options, type } = this.props
return <div className="row mt-20">
<div className="col-sm-6">
<FilteredMultiSelect
placeholder={`Select ${type}`}
buttonText="Add"
classNames={{
filter: 'form-control',
select: 'form-control',
button: 'btn btn btn-block btn-default',
buttonActive: 'btn btn btn-block btn-primary',
}}
onChange={this.handleSelect}
options={options}
selectedOptions={selectedOptions}
textProp="name"
valueProp="id"
/>
</div>
<div className="col-sm-6">
<FilteredMultiSelect
placeholder={`Visible ${type}`}
buttonText="Delete"
classNames={{
filter: 'form-control',
select: 'form-control',
button: 'btn btn btn-block btn-default',
buttonActive: 'btn btn btn-block btn-danger'
}}
onChange={this.handleDeselect}
options={selectedOptions}
textProp="name"
valueProp="id"
/>
</div>
</div>
}
}
export default class ChordFinal extends Component {
constructor(props) {
super(props);
this.state = {
master: {},
filterKeyword: {},
filterTaxonomy: {},
tooltip: {},
pFormat: d3.format(".1%"),
qFormat: d3.format(",.0f"),
rankList: [],
categoryList: [],
selectedRank: "",
selectedCategory: "",
keywordsOptions: [],
selectedKeywordsOptions: [],
taxonomyOptions: [],
selectedTaxonomyOptions: [],
};
this.importJSON = this.importJSON.bind(this);
this.addFilter = this.addFilter.bind(this);
this.updateChart = this.updateChart.bind(this);
this.updateTooltip = this.updateTooltip.bind(this);
this.reset = this.reset.bind(this);
this.setFilters = this.setFilters.bind(this);
}
toggleVisibility = () => this.setState({ visible: !this.state.visible })
updateTooltip = (data) => {
console.log(data);
this.setState({
tooltip: data
});
};
addFilter = (name) => {
let filters = this.state.filters;
filters[name] = {
name: name,
hide: true
};
this.setState({
hasFilters: true,
filters: filters
});
this.update()
};
// 1 - parse the data to get the list of ranks and categories
importJSON() {
// temporary dictionaries
const ranks = {}
const categories = {}
const master = {}
const rankList = []
const categoryList = []
TAXONOMY_DATA.fulldata.forEach(d => {
const rank = d.taxonomyRank;
const keyword = d.keywordCategory;
ranks[rank] = true;
categories[keyword] = true;
if (!master[rank]) {
master[rank] = {}
}
if (!master[rank][keyword]) {
master[rank][keyword] = []
}
master[rank][keyword].push(d);
})
// add ranks/categories to list
for (let key in ranks) {
if (ranks.hasOwnProperty(key)) {
rankList.push(key);
}
}
for (let key in categories) {
if (categories.hasOwnProperty(key)) {
categoryList.push(key);
}
}
console.log('rankList', rankList)
console.log('categoryList', categoryList)
console.log('master', master)
this.setState({
rankList,
categoryList,
master,
selectedRank: "superfamily",
selectedCategory: "Biological process",
}, () => {
this.updateList()
});
}
// create taxonomy/keyword list
updateList() {
// temporary dictionary
const keywords = {}
const taxonomies = {}
const { master, selectedRank, selectedCategory } = this.state
console.log(`master[${selectedRank}][${selectedCategory}]`)
if (master && master[selectedRank] && master[selectedRank][selectedCategory]) {
console.log(`master[${selectedRank}][${selectedCategory}]`, master[selectedRank][selectedCategory])
master[selectedRank][selectedCategory].forEach(d => {
keywords[d.keywordId] = d.keywordName;
taxonomies[d.taxId] = d.taxonomyName;
})
const keywordsOptions = [];
const taxonomyOptions = [];
// creates keyword list
for (let key in keywords) {
if (keywords.hasOwnProperty(key)) {
keywordsOptions.push({ id: key, name: keywords[key] });
}
}
// creates taxonomy list
for (let key in taxonomies) {
if (taxonomies.hasOwnProperty(key)) {
taxonomyOptions.push({ id: key, name: taxonomies[key] });
}
}
const selectedKeywordsOptions = keywordsOptions.slice();
const selectedTaxonomyOptions = taxonomyOptions.slice();
this.setState({
keywordsOptions,
selectedKeywordsOptions,
taxonomyOptions,
selectedTaxonomyOptions,
filterKeyword: keywords,
filterTaxonomy: taxonomies,
}, () => {
this.updateChart();
});
}
}
updateChart() {
const { master, selectedRank, selectedCategory, filterKeyword, filterTaxonomy } = this.state;
const data = master[selectedRank][selectedCategory];
if (data) {
this.child.drawChords(data.filter(d => (filterKeyword[d.keywordId] && filterTaxonomy[d.taxId])));
}
};
setFilters(item, input) {
let state = this.state;
state.filters[item.name] = {
name: item.name,
hide: input.target.checked
}
this.setState({
filters: state.filters
});
this.update(state);
}
reset() {
let state = this.state;
if (Object.keys(state.filters).length > 0 && state.hasFilters {
state.filters = {};
state.hasFilters = false;
this.setState({
filters: {},
hasFilters: false
});
this.updateChart();
}
}
componentDidMount() {
this.setState({ isComponentMount: true });
this.importJSON();
}
render =() => {
let state = this.state;
const { visible, rankList, categoryList, selectedRank, selectedCategory } = this.state
return <div>
<Sidebar.Pushable as={Segment}>
<Button onClick={this.toggleVisibility} icon className="navbar-toggle">
<Icon name="align justify"/>
</Button>
<Sidebar as={Menu} animation="overlay" width="very wide" direction="right" visible={visible} icon="labeled" vertical inverted>
<Icon className="close" size="large" onClick={this.toggleVisibility} />
<div className="row mt-50" />
<div className="row mt-20">
<div className="col-sm-6">
<Dropdown placeholder="Select Rank" selection value={selectedRank} options={rankList.map(
item => ({ key: item, text: item, value: item })
)} onChange={(e, data) => {
this.setState(
{ selectedRank: data.value },
() => {
this.updateList();
}
);
}} />
</div>
<div className="col-sm-6">
<Dropdown placeholder="Select Category" selection value={selectedCategory} options={categoryList.map(
item => ({ key: item, text: item, value: item })
)} onChange={(e, data) => {
this.setState(
{ selectedCategory: data.value },
() => {
this.updateList();
}
);
}} />
</div>
</div>
<AddRemoveSelection type="Taxonomy" options={this.state.taxonomyOptions} onChange={selectedTaxonomyOptions
{
this.setState({ selectedTaxonomyOptions });
}} />
<br />
<AddRemoveSelection type="Keywords" options={this.state.keywordsOptions} onChange={selectedKeywordsOptions
{
this.setState({ selectedKeywordsOptions });
}} />
<div className="row mt-20">
<div className="col-sm-12 text-left">
<button className="btn btn-primary" id="submit" onClick={this.toggleVisibility}>
Submit
</button>
<button className="btn btn-danger" id="reset" onClick={this.reset}>
Reset
</button>
</div>
</div>
</Sidebar>
<Sidebar.Pusher>
<Segment basic>
<div className="row" style={{ position: "relative" }}>
<div className="large-8 small-12" role="content">
<article style={{ width: 800, height: 800 }} id="chord">
{state.isComponentMount ?
<Chord updateTooltip={this.updateTooltip} addFilter={this.addFilter} onRef={ref => (this.child = ref)} filters={state.filters} />
: null}
</article>
</div>
<fieldset id="tooltip" placement="top" className="row">
<div className="small-6 small-12 ">
<h6>
Taxonomy Name: {state.tooltip.tname} <br /> Keyword Name: {state.tooltip.kname} <br /> Taxonomy ID: {state.tooltip.tid} <br /> Keyword Visibility: {state.tooltip.kwVizState} <br /> Taxonomy Visibility: {state.tooltip.taxVizState} <br /> Keyword ID: {state.tooltip.kid} <br /> Spect Count: {state.tooltip.tvalue}{" "}
</h6>
</div>
</fieldset>
</div>
</Segment>
</Sidebar.Pusher>
</Sidebar.Pushable>
</div>;
}
}
// 1 - parse the data to get the list of ranks and categories
importJSON() {
// temporary dictionaries
const ranks = {}
const categories = {}
const master = {}
const rankList = []
const categoryList = []
//to be placed for fullDataChord API fetch once it'S available
// d3.json('https://bitbucket.org/rohitkalva/viz/raw/11e7059eceaf571b12bf97d348cc157e5bf11fa3/fulldata.json')
TAXONOMY_DATA.fulldata.forEach(d => {
const rank = d.taxonomyRank;
const keyword = d.keywordCategory;
ranks[rank] = true;
categories[keyword] = true;
if (!master[rank]) {
master[rank] = {}
}
if (!master[rank][keyword]) {
master[rank][keyword] = []
}
master[rank][keyword].push(d);
})
// add ranks/categories to list
for (let key in ranks) {
if (ranks.hasOwnProperty(key)) {
rankList.push(key);
}
}
for (let key in categories) {
if (categories.hasOwnProperty(key)) {
categoryList.push(key);
}
}
console.log('rankList', rankList)
console.log('categoryList', categoryList)
console.log('master', master)
this.setState({
rankList,
categoryList,
master,
// selectedRank: rankList[0],
// selectedCategory: categoryList[0],
selectedRank: "superfamily",
selectedCategory: "Biological process",
}, () => {
this.updateList()
});
}
// create taxonomy/keyword list
updateList() {
// temporary dictionary
const keywords = {}
const taxonomies = {}
const { master, selectedRank, selectedCategory } = this.state
console.log(`master[${selectedRank}][${selectedCategory}]`)
if (master && master[selectedRank] && master[selectedRank][selectedCategory]) {
console.log(`master[${selectedRank}][${selectedCategory}]`, master[selectedRank][selectedCategory])
master[selectedRank][selectedCategory].forEach(d => {
keywords[d.keywordId] = d.keywordName;
taxonomies[d.taxId] = d.taxonomyName;
})
const keywordsOptions = [];
const taxonomyOptions = [];
// creates keyword list
for (let key in keywords) {
if (keywords.hasOwnProperty(key)) {
keywordsOptions.push({ id: key, name: keywords[key] });
}
}
// creates taxonomy list
for (let key in taxonomies) {
if (taxonomies.hasOwnProperty(key)) {
taxonomyOptions.push({ id: key, name: taxonomies[key] });
}
}
const selectedKeywordsOptions = keywordsOptions.slice();
const selectedTaxonomyOptions = taxonomyOptions.slice();
this.setState({
keywordsOptions,
selectedKeywordsOptions,
taxonomyOptions,
selectedTaxonomyOptions,
filterKeyword: keywords,
filterTaxonomy: taxonomies,
}, () => {
this.updateChart();
});
}
}
updateChart() {
const { master, selectedRank, selectedCategory, filterKeyword, filterTaxonomy } = this.state;
const data = master[selectedRank][selectedCategory];
if (data) {
this.child.drawChords(data.filter(d => (filterKeyword[d.keywordId] && filterTaxonomy[d.taxId])));
}
};
setFilters(item, input) {
let state = this.state;
state.filters[item.name] = {
name: item.name,
hide: input.target.checked
}
this.setState({
filters: state.filters
});
this.update(state);
}
reset() {
let state = this.state;
if (Object.keys(state.filters).length > 0 && state.hasFilters) {
state.filters = {};
state.hasFilters = false;
this.setState({
filters: {},
hasFilters: false
});
this.updateChart();
}
}
componentDidMount() {
this.setState({ isComponentMount: true });
this.importJSON();
}
React doesn't mind how you do API(URL) call. you can choose whatever kind of AJAX library you like for this task. The simplest way is this.
importJSON() {
const ranks = {}
const categories = {}
const master = {}
const rankList = []
const categoryList = []
var request = new XMLHttpRequest();
request.open('GET', '/my/url', true);
request.setRequestHeader('Content-Type', 'application/json');
request.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
this.state({
TAXONOMY_DATA: xhttp.responseText
}, ()=> {
this.state.TAXONOMY_DATA.fulldata.forEach(d => {
const rank = d.taxonomyRank;
const keyword = d.keywordCategory;
ranks[rank] = true;
categories[keyword] = true;
if (!master[rank]) {
master[rank] = {}
}
if (!master[rank][keyword]) {
master[rank][keyword] = []
}
master[rank][keyword].push(d);
});
});
}
};
request.send();
// add ranks/categories to list
for (let key in ranks) {
if (ranks.hasOwnProperty(key)) {
rankList.push(key);
}
}
for (let key in categories) {
if (categories.hasOwnProperty(key)) {
categoryList.push(key);
}
}
console.log('rankList', rankList)
console.log('categoryList', categoryList)
console.log('master', master)
this.setState({
rankList,
categoryList,
master,
selectedRank: "superfamily",
selectedCategory: "Biological process",
}, () => {
this.updateList()
});
}
Instead of require
at the beginning,
const TAXONOMY_DATA = require(../../assets/chord.json);
Utilize fetch API :
constructor(props) {
super(props);
this.state = {
selectedOptions: [],
TAXONOMY_DATA: null
}
}
importJSON() {
const ranks = {}
const categories = {}
const master = {}
const rankList = []
const categoryList = []
fetch("https://.../chord.json")
.then( (response) => {
return response.json()
})
.then( (json) => {
this.setState({
TAXONOMY_DATA: json
}, ()=> {
this.state.TAXONOMY_DATA.fulldata.forEach(d => {
const rank = d.taxonomyRank;
const keyword = d.keywordCategory;
ranks[rank] = true;
categories[keyword] = true;
if (!master[rank]) {
master[rank] = {}
}
if (!master[rank][keyword]) {
master[rank][keyword] = []
}
master[rank][keyword].push(d);
...
this.setState({
rankList,
categoryList,
master,
selectedRank: "superfamily",
selectedCategory: "Biological process",
}, () => {
this.updateList()
});
});
});
}
And because you deploy importJSON
in componentDidMount()
, which means you ask for data after all of the element have been rendered once. This would cause problem cause you have many value assignment in importJSON
and you don't have those values when the first rendering, you need make sure this.state.TAXONOMY_DATA
have been settled and then assigned value by
render =() => {
...
if(this.state.TAXONOMY_DATA) {
const { visible, rankList, categoryList, selectedRank, selectedCategory } = this.state`
return (<div>...</div>)
} else {
return null;
}
...
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.