如何遍历对象以使用打字稿查找特定值并做出反应?

时间:2020-07-28 13:41:20

标签: reactjs typescript

如果至少有一个订单或子区域至少有一个订单的状态为“接受”或“完成”,我想隐藏一个按钮。 当任何一个项目的订单状态至少为“接受”或“完成”的一个区域或子区域订单的状态为“已接受”或“完成”的至少一个区域时,如何隐藏“隐藏我”菜单项。

下面是我要处理的项目的反应代码

function Parent() {
    const item = {
        owner: {
            id: '1',
            cognitoId: '2',
        },
        areas: [{
            id: '1',
            orders: [
                {
                    id: '1',
                    status: 'ASSIGNED',
                }, {
                    id: '2',
                    status: 'ACCEPTED',
                } 
            ],
            subAreas: [
                {
                    id: '1',
                    orders: [
                        {
                            id: '4',
                            status: 'DONE',
                        }
                    ],
                }
            ]
        }, {
            id: '2',
            orders: [{
                    id: '3',
                    status: 'ASSIGNED',
                }, {
                    id: '4',
                    status: 'ACCEPTED',
                }
            ],
            subAreas: [{
                    id: '2',
                    orders: [{
                            id: '5',
                            status: 'DONE',
                        }, {
                            id: '6',
                            status: 'ACCEPTED',
                        }
                    ],
                }
            ]
        }
    ]
}

return ({
    item && item.owner && item.owner.cognitoId && (
         < Menu > Hide me <  / Menu > )
});

}

此项目是有关数据外观的参考。
有关更多信息... Item的类型为Item,如下所示

export interface Item {
    id: string;
    name: string;
    areas?: Area[];
}

export interface Area {
    id: string;
    Orders?: Order[];
    subAreas?: Area[];
}

export interface Order {
    id: string;
    status: OrderStatus; //this is the one we are looping through
}

export interface OrderStatus {
    NEW = 'NEW',
    ASSIGNED = 'ASSIGNED',
    SENT = 'SENT',
    ACCEPTED = 'ACCEPTED',
    REJECTED = 'REJECTED',
    DONE = 'DONE',
}

我尝试过的操作如下

const hasDoneAccepted = () => {
   return Object
      .keys(item)
          .some(key =>
              (key === 'status' &&
              ['DONE', 'ACCEPTED'].indexOf(item[key]) > -1) ||
              (typeof item[key] === 'object' &&
              hasDoneAccepted(item[key])));
 }

但这给了我类似下面的错误,

元素隐式具有任何类型,因为不能在索引类型“ Item”上使用“状态”类型的表达式。属性状态在“项目”类型上不存在。

我是使用打字稿的新手,不知道出了什么问题。有人可以帮我吗谢谢。

编辑: 使用提供的解决方案

const hasAcceptedOrDoneOrders = 
    item.areas?.reduce<Order[]>((acc, area) => { //error here
        area.orders?.forEach(order => acc.push(order));
        area.subAreas?.forEach(subArea => subArea.orders?.forEach(order => 
            acc.push(order)));
            return acc;
    }, [])
    .some(order => order.status === "ACCEPTED" || order.status === "DONE");
 }

这给了我一行

item.areas?.reduce<Order[]>((acc, area) => 

“解析错误:需要表达”

2 个答案:

答案 0 :(得分:0)

循环遍历对象始终是一种选择。我也会使用辅助方法。像这样:

hideBool = false;
for(cost area of item.areas()) {
    if(hideBool) { break; }
    hideBool = this.checkArray(area.orders);
    if(!hideBool) { 
            for(const subArea of area.subAreas) {
        hideBool = this.checkArray(subArea);
        if(hideBool) { break; }
            } 
        }
}


checkArray(array: any[]) {
    for( const item in array) {
             if(item.status === 'ACCEPTED' || item.status === 'DONE') {
                   return true;
        }
        }
    return false;
} 

答案 1 :(得分:0)

这是编写过滤器功能的方法:

const hasAcceptedOrDoneOrders = 
    item.areas?.reduce<Order[]>((acc, area) => {
        area.orders?.forEach(order => acc.push(order));
        area.subAreas?.forEach(subArea => subArea.orders?.forEach(order => acc.push(order)));
        return acc;
      }, [])
      .some(order => order.status === "ACCEPTED" || order.status === "DONE");

并使用它有条件地显示React元素:

return !hasAcceptedOrDoneOrders && <Menu>Hide me</Menu>;

但是,要消除所有TypeScript语法错误,您需要正确键入item对象并修复数据模式:

const item: Item = {
    id: "1",
    name: "Item1",
    owner: { id: "1", cognitoId: "2" },
    areas: [
      {
        id: "1",
        orders: [
          { id: "1", status: OrderStatus.ASSIGNED },
          { id: "2", status: OrderStatus.ACCEPTED }
        ],
        subAreas: [
          {
            id: "1",
            orders: [{ id: "4", status: OrderStatus.DONE }]
          }
        ]
      },
      {
        id: "2",
        orders: [
          { id: "3", status: OrderStatus.ASSIGNED },
          { id: "4", status: OrderStatus.ACCEPTED }
        ],
        subAreas: undefined
      }
    ]
  };

模式:

interface Item {
  id: string;
  name: string;
  areas?: Area[];
  owner: any;
}

enum OrderStatus {
  NEW = 'NEW',
  ASSIGNED = 'ASSIGNED',
  SENT = 'SENT',
  ACCEPTED = 'ACCEPTED',
  REJECTED = 'REJECTED',
  DONE = 'DONE',
}