0

I'm trying to set routes in hookrouter dynamically. Current routes are an array of four objects which are mapped into lis:

const routes = [
        { href: '/', label: 'Root' },
        { href: '/About', label: 'About' },
        { href: '/Sites', label: 'Sites' },
        { href: '/Blog', label: 'Blog' }
    ].map(route => {
        route.key = `nav-route-${route.href}-${route.label}`;
        return route;
    });

// End result I need:
// export const directions = {
//  '/': () => <Root />,
//  '/About': () => <About />,
//  '/Sites': () => <Sites />,
//  '/Blog': () => <Blog />
// };

// This solution comes very close, but complains of PascalCase:
export const directions = routes.reduce(
    (object, Item) =>
        Object.assign(object, { [Item.href]: () => <Item.label /> }),
    {});


const NavList = props => {
    return (
        <NavContainer>
            <ul>
                {routes.map(({ key, href, label }) => (
                    <A href={href} key={key} className='route-link'>
                        <li className={href === window.location.pathname ? 'active' : null}>
                            {label}
                        </li>
                    </A>
                ))}
            </ul>
        </NavContainer>
    );
};

export default NavList;

Update: So I originally submitted this question when I was having issues putting functions into an object, but Object.assign() inserts functions into the empty object without issue.

Now the problem I'm having is React complaining about PascalCase. Here's the exact error:

index.js:1 Warning: <About /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.

But the routes array has labels with capitalized letters. I tried capitalizing 'I' in Item for the Object.assign() method, which interestingly React accepts the first route and errors on the second route if the I is capitalized.

AveryFreeman
  • 1,061
  • 2
  • 14
  • 23
  • Where do the components come from, and what are their actual names? – Bergi Jul 19 '20 at 21:03
  • // route objects in array, keys are 'href' and 'label': const routes = [ { href: '/', label: 'Root' }, { href: '/About', label: 'About' }, { href: '/Sites', label: 'Sites' }, { href: '/Blog', label: 'Blog' } ]; // Array.reduce extracts objects, Object.assign maps values to new object with arrow functions and components as values: const directions = routes.reduce( (object, Item) => Object.assign(object, { [Item.href]: () => }), {}); – AveryFreeman Jul 20 '20 at 02:13
  • That's the code you already posted. I meant where are you defining the components like `` and ``? – Bergi Jul 20 '20 at 09:42
  • They're defined in separate files. They're imported at the top (omitted). They work properly with the `directions` object written by hand (the commented-out portion). The `Array.reduce(Object.assign())` code appears to make an object just like `directions`, but React complaints about it - either because it's being generated dynamically, or there's something just slightly different about it I'm not seeing in console.log. – AveryFreeman Jul 20 '20 at 18:04
  • "*They're imported at the top (omitted).*" - ah, now we're talking. The problem is that `Item.label` is a string, not a reference to the imported component. You need to pass the component itself. You could use an object or `Map` to look it up by your label, though. – Bergi Jul 20 '20 at 19:00
  • Ohhh... I didn't think of that. Thanks for sticking with me - would you mind answering w/ an example and I'll try it out? – AveryFreeman Jul 20 '20 at 19:24
  • I've already closed it as a duplicate :-) Maybe also have a look at [this question](https://stackoverflow.com/q/31776949/1048572) for how to access the classes dynamically. – Bergi Jul 20 '20 at 19:36

0 Answers0