Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Render JSX-element conditionally based on whether source object has deeply nested properties with certain values

I want to hide a button if there is atleast one order or subareas that at least one orders whose status 'ACCEPTED' or 'DONE'.

How can I hide the "Hide me" Menu item when either item has at least one area with order status 'ACCEPTED' OR 'DONE' or at least one area with subareas order with status 'ACCEPTED' or 'DONE'.

Below is the react code with the item I am trying to process

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

EDIT

strong text

As per the solution provided i have tried like below,

const hasDoneAccepted = () => {
    Object
        .keys(item)
            .some(key =>
                (key === 'status' &&
                    ['DONE', 'ACCEPTED'].includes(item[key])) || //error                  //here
                    (typeof item[key] == 'object' && //error here
                    hasDoneAccepted(item[key])) //error here
};

But this gives me error

Element implicitly has any type because expression of type "status" cant be used on index type 'Item'. property status doesnt exist on type 'Item'.

EDIT2strong text

based on solution for typescript implemented like below,

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

console.log("output***", hasDoneAccepted(item));

this doesnt give any errors but in runtime the app breaks. and in the console i see the error.

"cannnot convert undefined or null to object"

like image 351
saritha Avatar asked Mar 20 '26 00:03

saritha


1 Answers

You may traverse recursively (e.g. with Array.prototype.some()) your source object all deep through to find out, whether some key, named status has value either'DONE' or 'ACCEPTED' within nested properties:

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',}],}]}]},

      hasDoneAccepted = o =>
        Object
          .keys(o)
          .some(key => 
            (key == 'status' &&
            ['DONE', 'ACCEPTED'].includes(o[key])) ||
            (typeof o[key] == 'object' &&
            hasDoneAccepted(o[key])))
            
console.log(hasDoneAccepted(item))

So, your conditional rendering may look something, like that:

function Parent() {
   const hasDoneAccepted = ..
   ..
   return !!item?.owner?.cognitoId && hasDoneAccepted(item) && 
          (<Menu>Hide me</Menu>)
}
like image 195
Yevgen Gorbunkov Avatar answered Mar 21 '26 14:03

Yevgen Gorbunkov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!