简体   繁体   中英

how to convert filepath to url in reactjs

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM