如何使用打字稿根据所选选项卡显示对象的相关信息并做出反应?

时间:2020-08-14 12:29:49

标签: reactjs typescript

我具有如下数据结构(对象)

const Items = {
    id: '1',
    Orders: [
        {
            id: '2',
            title: 'Order1',
        }
        {
            id: '3',
            title: 'Order2',
        }
    ],
    subItems: [
        { 
            id: '1',
            Orders: [
                {
                    id: '1',
                    title: 'subitem1-order1',
                    status: 'new',
                }
                {
                    id: '2',
                    title: 'subitem1-order2',
                    status: 'done',
                }
            ],
        }
        { 
            id: '2',
            Orders: [
                {
                    id: '1',
                    title: 'subitem2-order1',
                    status: 'new',
                }
                {
                    id: '2',
                    title: 'subitem2-order2',
                    status: 'done',
                }
            ],
        }
    ]
}

从以上数据可以看出,items对象具有Orders和subItems也具有多个Orders。

我有两个标签。订单和子项目订单。当用户单击“订单”选项卡时,我应该只列出“项目”对象的“订单”,因此结果应为

Order1和Order2

类似地,当用户单击选项卡子项命令时,结果应为

subitem1-order1,subitem1-order2,subitem2-order1和subitem2-order2

还有所有所有,新的,完成的,接受的过滤器div。默认为全部,表示所有新的,已完成的或已接受的状态的所有顺序。 如果用户单击“新建过滤器”,它将列出新状态的订单(订单和子项目订单) 如果用户单击“完成的过滤器”,则会列出状态完成的订单(订单和子项目订单) 如果用户单击接受的过滤器,则会列出状态为接受的订单(订单和子项目订单)。

下面的

是我的代码,当前将Orders和subItem订单放入对象数组,并按照创建顺序将它们一起列出。我添加了尚无法使用的标签。

export enum TabOptions {
    Orders = 'Orders',
    SubItemOrders = 'SubItemOrders',
}

function getAllOrders(items) {
    return [
        ...(items.Orders || []),
        ...(items.subItems
        ? items.subItems.reduce((acc: any, subItem) => {
            return [...acc, ...(subItem.Orders || [])];
        }, [])
          : []),
    ];
}

export const useOrdersByFilter = (items) => {
    return React.useMemo(() => {
        const Orders = getAllOrders(items); //this groups all orders and subitem orders into one array of objects

        const sortedOrders = orderBy(Orders,
            ({ startDate }) => new Date(startDate),
            ['asc']
        );

        const delayedOrders = sortedOrders.filter(o => {
            const now = moment();
            const end = moment(o.endDate);
            const isDelayed =
                o.status !== OrderStatus.DONE && end.isBefore(now, 'day');
            return isDelayed;
        });

        const byStatus = groupBy(sortedOrders, 'status');

        return {
            [OrderFilter.ALL]: sortedOrders,
            [OrderFilter.COMPLETE]: byStatus[OrderStatus.DONE] || [],
            [OrderFilter.DELAYED]: delayedOrders,
        };
    }, [item]);
};


function Parent () {
    const items; //this has value as the items data structure that i mentioned above.
    const [selectedTab, setSelectedTab] = React.useState(TabOptions.Orders);//this             keeps track of tab that user clicked.defaulted to Orders tab.
    const [activeFilter, setActiveFilter] = React.useState<OrderFilter>(
        OrderFilter.ALL
    ); //this keeps track of filter type that user selected. default to all.


    const OrdersByFilter = useOrdersByFilter(items);
    const allOrders = OrdersByFilter[OrderFilter.ALL] || [];

    return (
        <Wrapper>
            <Content>
                <span> title</span>
                <Tabs>
                    <Tab
                        onClick={() => setSelectedTab(TabOptions.Orders)}
                        className={selectedTab === TabOptions.Orders ? 'active' : ''}
                    >
                        <span>Orders</span>
                    </Tab>
                    <Tab
                        onClick={() => setSelectedTab(TabOptions.SubItemOrders)}
                        className={selectedTab === TabOptions.SubItemOrders ?             'active' : ''}
                    >
                        <span>subItem-Orders</span>
                    </Tab>
                </Tabs>
                {allOrders.length > 0 &&
                    <OrderFilters //this component displays the filter bars based on  the orders  that have been added recently. if there is new Order added by user of status say 'done' then it adds filter for done. similarly for others too.
                        activeFilter={activeFilter}
                        onFilterChange={setActiveFilter}
                        Orders={allOrders}
                    </OrderFilter>
                }

                <OrdersWrapper> //this is the one that lists the orders (both the orders and subitem-orders in the same list
                    <OrderList Orders={OrdersByFilter[activeFilter]} /> 
                </OrdersWrapper>
            </Content>
        </Wrapper>
    );
}
  

    
//the OrderList component lists the orders (both the orders and subitemorders)

function OrderList({Orders}:Props) {
    return (
        {item.data.map(o => {
            return (
              <OrderCardWrapper key={o.id}>
                <OrderCard data={o} /> //this is  div that displays order info.
              </OrderCardWrapper>
            );
          })}
      );
 }

上面的代码在一个列表中同时显示订单和子项目订单。但现在我想将它们分成几部分。当用户选择“订单”选项卡时,只能看到订单。当用户点击“子订单”标签时,只能看到子订单。

我该如何解决以上代码。有人可以帮我吗谢谢。

1 个答案:

答案 0 :(得分:1)

一种可能的解决方案,我只将相关代码放在这里:

首先将 getAllOrders 分成2个函数 (您可以摆脱...运算符,因为reduce会进行浅表复制)

function getAllOrders(items) {
    return [
        ...(items.Orders || []),
    ];
}


function getAllSubOrders(items) {
    return 
        items.subItems ? items.subItems.reduce((acc: any, subItem) => {
             return [...acc, ...(subItem.Orders || [])];
        }, [])
        : []
    ;
}

将getAllOrder调用移至Parent函数,这样便可以为每个项目(订单和子订单)调用它

function Parent() {
    ...       
    const Orders = getAllOrders(items);
    const SubOrders = getAllSubOrders(items);
    const OrdersByFilter = useOrdersByFilter(Orders);
    const SubOrdersByFilter = useOrdersByFilter(SubOrders);

当然,现在 useOrdersByFilter 接受订单而不是商品。

export const useOrdersByFilter = (Orders) => {
    return React.useMemo(() => {

        const sortedOrders = orderBy(Orders,
        ...

返回上级功能,应根据用户选择(项目或子项目)初始化 allOrders

    const allOrders = (selectedTab === TabOptions.SubItemOrders ? SubOrdersByFilter[OrderFilter.ALL] : OrdersByFilter[OrderFilter.ALL]) || [];