简体   繁体   中英

How do I map a json object to specific json structure

I am using antd cascader to fill options in a nice dropdown

https://ant.design/components/cascader/

My goal is: 1. Load a set of options from a remote test api (1st level of the cascade) 2. When the user clicks on any option, then load the second level (comments)

I am using this rest api as example:

https://jsonplaceholder.typicode.com/

The example needs the data like this:

const options = [{
    value: 'zhejiang',
    label: 'Zhejiang',
    isLeaf: false,
  }, {
    value: 'jiangsu',
    label: 'Jiangsu',
    isLeaf: false,
  }];

So this is my code:

import React, { Component } from 'react';
import { Row, Col, Tabs, Menu, Dropdown, Button, Icon, message } from 'antd';
import PageHeader from '../../components/utility/pageHeader';
import Box from '../../components/utility/box';
import LayoutWrapper from '../../components/utility/layoutWrapper';
import ContentHolder from '../../components/utility/contentHolder';
import basicStyle from '../../settings/basicStyle';
import IntlMessages from '../../components/utility/intlMessages';
import { Cascader } from 'antd';

const options = [{
    value: 'zhejiang',
    label: 'Zhejiang',
    isLeaf: false,
  }, {
    value: 'jiangsu',
    label: 'Jiangsu',
    isLeaf: false,
  }];

export default class extends Component {

    constructor(props) {
        super(props);
        this.state = {options};
        this.loadData = this.loadData.bind(this)
    }

    onChange(value, selectedOptions) {
        console.log(value, selectedOptions);
    }

    loadData(selectedOptions){
            fetch('https://jsonplaceholder.typicode.com/posts')
            .then(response => response.json())
            .then(json => console.log(json));

      }


    render(){
        const { rowStyle, colStyle, gutter } = basicStyle;
        const TabPane = Tabs.TabPane;

        return (
        <div>
            <LayoutWrapper>
            <PageHeader>{<IntlMessages id="pageTitles.PageAdministration" />}</PageHeader>
            <Row style={rowStyle} gutter={gutter} justify="start">
            <Col md={12} sm={12} xs={24} style={colStyle}>
                <Box
                title={<IntlMessages id="pageTitles.siteCollectionsTitle" />}
                subtitle={<IntlMessages id="pageTitles.siteCollectionsTitle" />}
                >
                <ContentHolder>
                    <Cascader
                                options={this.state.options}
                                loadData={this.loadData}
                                onChange={this.onChange}
                                changeOnSelect
                    />
                </ContentHolder>
                </Box>
            </Col>
            </Row>
        </LayoutWrapper>
        </div>
        );
  }
}

I have 2 basic questions

  1. How do I conver the json from the first response and bind it to the control
  2. Once the user selects an option, how do I load the 2nd level of options? (eg comments per post from above rest api)
  1. You can save the api response to your local state with setState .
  2. Take advantage of loadData props of Cascader component

I did not follow your code exactly, but I hope this will help you to get the idea:

const { Cascader } = antd;


class LazyOptions extends React.Component {
  state = {
    options: [],
  };

  componentDidMount() {
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then(response => response.json())
      .then(json => {
        console.log(json);
        const firstLevelOptions = json.map(post => ({
          value: post.id,
          label: post.title,
          isLeaf: false    
        }));
        this.setState({
          options: firstLevelOptions
        })
      }
    );
  }

  onChange = (value, selectedOptions) => {
    console.log("value:", value, "selectedOptions", selectedOptions);
  }

  loadData = (selectedOptions) => {
    console.log("loaddata", selectedOptions);

    const targetOption = selectedOptions[selectedOptions.length - 1];
    targetOption.loading = true;

    // load options lazily
    fetch(`https://jsonplaceholder.typicode.com/posts/${targetOption.value}/comments`)
      .then(response => response.json())
      .then(json => {
        targetOption.loading = false;
        console.log(json);
        const secondLevelOptions = json.map(comment => ({
          value: comment.id,
          label: comment.body,
          isLeaf: true    
        }));
        targetOption.children = secondLevelOptions;
        this.setState({
          options: [...this.state.options],
        });
      }
    );
  }

  render() {
    return (
      <Cascader
        options={this.state.options}
        loadData={this.loadData}
        onChange={this.onChange}
        changeOnSelect
      />
    );
  }
}

ReactDOM.render(<LazyOptions />, mountNode);

Try on codepen

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