1

How can I iteratively render nested components in react?

(as I understood, recursion is more expensive in terms of performance?)

P.S. nesting levels can be unlimited

Example:

"comments": [
                {
                    "name": "1comment",
                    "body": "1comment",
                    "date": "2019-05-15T15:56:15.694116Z",
                    "id": "0179ef41-fdb6-4700-a4dc-6d7bbc54385a",
                    "parent": null,
                    "reply": []
                },
                {
                    "name": "2comment",
                    "body": "2comment",
                    "date": "2019-05-17T13:59:51.167188Z",
                    "id": "1ef06878-58b5-48b0-9349-73986ab66bb4",
                    "parent": null,
                    "reply": [
                        {
                            "name": "2-1-comment",
                            "body": "2-1-comment",
                            "date": "2019-05-21T22:32:44.998207Z",
                            "id": "514aa634-08bd-4ca3-8a1a-eb10846808ed",
                            "parent": "5a01211d-3ee9-4bf6-9a50-462a8277898a",
                            "reply": [
                                {
                            "name": "2-1-1-comment",
                            "body": "2-1-1-comment",
                            "date": "2019-05-21T22:32:44.998207Z",
                            "id": "514aa634-08bd-4ca3-8a1a-eb10846808ed",
                            "parent": "5a01231d-3119-4bf6-9a50-462a8277898a",
                            "reply": []
                            }
                            ]
                        }
                    ]
                },
                {
                    "name": "3comment",
                    "body": "3comment",
                    "date": "2019-05-19T12:07:15.613266Z",
                    "id": "5a01231d-3ee9-4bf6-9a50-462a8277898a",
                    "parent": null,
                    "reply": [
                        {
                            "name": "3-1-comment",
                            "body": "3-1-comment",
                            "date": "2019-05-21T22:32:44.998207Z",
                            "id": "514aa634-08bd-4ca3-8a1a-eb10846808ed",
                            "parent": "5a01231d-3ee9-4bf6-9a50-462a8277198a",
                            "reply": []
                        }
                    ]
                }
]
kca
  • 4,856
  • 1
  • 20
  • 41
norovone
  • 11
  • 2
  • 1
    If nesting levels are unlimited, then you need to use recursion. For something simple like this performance will not be a problem. – Asen Mitrev Oct 08 '21 at 07:19
  • The tree is not simple, but with more than 5 levels of nesting, after 5 levels, lags and brakes begin, because recursion is costly in terms of performance, an iterative approach (through a stack) is less resource-intensive, the question is how to draw nested components into react using an iterative approach – norovone Oct 08 '21 at 08:25

1 Answers1

0

The basic principle would be to store the "path" to the current element in some way, then

  • push if there is a child,
  • iterate over current list,
  • pop if the current list is done.

E.g. stack = [ 2, 1, 3 ] in your case would represent element.reply[ 2 ].reply[ 1 ].reply[ 3 ].

I believe you have to store as well the lengths of all the lists of each path (to be able to iterate every level), which could be stored directly in the stack, but that in turn makes it more confusing to get back the index when you need it.

E.g.:

const stack = [ comments.length ];
while( stack.length > 0 ){

    // -- get current item by the "path" (i.e. by the stack)
    const currentItem = stack.reduce( (acc, value, index ) => {
        const list = index === 0 ? acc : acc.reply; // root or not root
        return list[ list.length - value ];
    },  comments);

    // --
    if( currentItem ){
        console.log( stack, currentItem && currentItem.name );
        if ( currentItem.reply && currentItem.reply.length > 0 ) {
            stack.push(currentItem.reply.length);  // level deeper
        } else {
            stack[stack.length - 1]--;  // next sibling
        }
    } else {
        stack.pop();                // level up
        stack[stack.length - 1]--;  // next sibling
    }
}

About the performance:

I guess the iterative approach becomes necessary only for really huge amounts of data. For 'normal' data the recursion should be able to keep a structure of 5 or even 50 levels deep in memory. E.g. I used the iterative approach once for millions of XML lines (not limited, so theoretically infinite), deeply nested. I guess for thousands I would still have used recursion.

Tip: Do you use a pattern like acc = [ ...acc, item ] (whick is common in React) ? That becomes slow at a scale of hundreds or thousands. Then you might want to have a look at Is mutating accumulator in reduce function considered bad practice

kca
  • 4,856
  • 1
  • 20
  • 41