0

Is it possible to flatten this collections using lodash and concatenate the path strings? I tried to but can only reach second level, I want to flatten it regardless the depth as long as there's a pageRouter array inside the object

{
    component: () => React.createElement('div', undefined, 'Parent Page'),
    exact: true,
    pageTitle: 'Parent',
    path: '/parent',
    pageRoute: [
      {
        component: () => React.createElement('div', undefined, 'Child Page'),
        exact: true,
        pageTitle: 'Child',
        path: '/child',
        pageRoute: [
          {
            component: () =>
              React.createElement('div', undefined, 'Grandchild Page'),
            exact: true,
            pageTitle: 'GrandChild',
            path: '/grandchild',
          },
        ],
      },
    ],
  },

to this?

 [
    {
      component: () => React.createElement('div', undefined, 'Parent Page'),
      exact: true,
      pageTitle: 'Parent',
      path: '/parent',
    },
    {
      component: () => React.createElement('div', undefined, 'Child Page'),
      exact: true,
      pageTitle: 'Child',
      path: '/parent/child',
    },
    {
      component: () => React.createElement('div', undefined, 'Grandchild Page'),
      exact: true,
      pageTitle: 'GrandChild',
      path: 'parent/child/grandchild',
    },
  ],

attempted code

const = routeList = _.flatMapDeep(publicRoutes, (x) => {
   if (x.pageRoute) {
      return [x, { ...x.pageRoute, path: x.path + _.head(x.pageRoute)?.path }];
     } else return x;
   });
3
  • Did you try flatten or flattenDeep? Commented Nov 4, 2020 at 21:08
  • Could you post your attempted code? Commented Nov 4, 2020 at 21:09
  • _.flatMapDeep(publicRoutes, (x) => { if (x.pageRoute) { return [x, { ...x.pageRoute, path: x.path + _.head(x.pageRoute)?.path }]; } else return x; }) Commented Nov 4, 2020 at 21:18

1 Answer 1

2

No need for lodash. Since this is a nested structure, it seems like a good opportunity for a recursive function:

const components = [
  {
    component: () => React.createElement('div', undefined, 'Parent Page'),
    exact: true,
    pageTitle: 'Parent',
    path: '/parent',
    pageRoute: [
      {
        component: () => React.createElement('div', undefined, 'Child Page'),
        exact: true,
        pageTitle: 'Child',
        path: '/child',
        pageRoute: [
          {
            component: () =>
              React.createElement('div', undefined, 'Grandchild Page'),
            exact: true,
            pageTitle: 'GrandChild',
            path: '/grandchild',
          },
        ],
      },
    ],
  }
];

const flattenedComponents = [...flattenComponents(components, '')];

console.log(flattenedComponents);

function* flattenComponents(nestedComponents, pathPrefix) {
  for (const { pageRoute: routes, path, ...component } of nestedComponents) {
    const newPath = `${pathPrefix}${path}`;
    yield { ...component, path: newPath };
    if (routes) {
      yield* flattenComponents(routes, newPath);
    }
  }
}

Sign up to request clarification or add additional context in comments.

4 Comments

Wow this is great! I haven't thought of a function generator, would it make difference using a simple loop?
Simple loop is also ok; I just find generators elegant.
I'm getting flattenComponents' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. this error as I use typescript, function* flattenComponents(nestedComponents:PageRoute[], pathPrefix: string = '') still not used to generator so I don't know where to infer the return type
You can type the return value as Iterable<Foo> where Foo has the structure of each component object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.