【问题标题】:How do I map a json object to specific json structure如何将 json 对象映射到特定的 json 结构
【发布时间】:2019-01-31 18:45:26
【问题描述】:

我正在使用 antd cascader 在一个不错的下拉列表中填充选项

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

我的目标是: 1. 从远程测试 api 加载一组选项(级联的第一级) 2.当用户点击任意选项时,加载第二层(cmets)

我以这个 rest api 为例:

https://jsonplaceholder.typicode.com/

示例需要这样的数据:

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

这是我的代码:

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>
        );
  }
}

我有 2 个基本问题

  1. 如何从第一个响应中转换 json 并将其绑定到控件
  2. 一旦用户选择了一个选项,我如何加载第二级选项? (例如,来自上面 rest api 的每个帖子的 cmets)

【问题讨论】:

  • 你得到的数据的 JSON 结构是什么?
  • 他们在这里:jsonplaceholder.typicode.com/posts,只需要 id 和 title 将其映射到 value 和 label
  • 那么,在第一个级联中,您想查看所有用户,然后在单击一个时,查看他的所有帖子?
  • 在第一个级联上,发帖,在第二个 cmets 上,它只是为了示例,稍后在现实生活中我需要将 apis 更改为其他东西,但在我知道如何做之后这个公共的rest api,很容易改变它

标签: javascript reactjs typescript antd


【解决方案1】:
  1. 您可以使用 setState 将 api 响应保存到您的本地状态。
  2. 利用 Cascader 组件的 loadData 属性

我没有完全按照你的代码,但我希望这能帮助你理解这个想法:

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

【讨论】:

    猜你喜欢
    • 2015-06-27
    • 1970-01-01
    • 1970-01-01
    • 2019-05-27
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 2012-04-16
    • 2017-04-11
    相关资源
    最近更新 更多