reactjsreact-routercore-ui

React route, use the same component with different props/parameters on CoreUI


Let's say I have a React component called Component1, where it makes plots based on the data provided --

import data_A from "./some/folder/A";
import data_B from "./some/folder/B";
.
.
.
import data_Z from "./some/folder/Z";

const Component1 = (props) => {
    var data = /* decide which data to load using props, will come from a nav link click event */
    return(/* render component with data */);
}

I have another file where I specify all the routes to the components:

const Component1 = React.lazy(() => import("./views/components/Component1"));

routes = [
    { path: "/components", name: "Component1", component: Component1, }
    // there are more components but they are not relevant here.
];

and I build the <Switch/> like this:

<Switch>
    {routes.map((route, idx) => {
        return(route.component && (
            <Route key={idx} path={route.path} exact={route.exact} name={route.name}
                render={(props) => (<route.component {...props} />)}
            />
        ));
    })}
    <Redirect from="/" to="/components" />
</Switch>

On my app, I have a navigation bar, which is built on the fly from a list of object specified in a variable. Here each nav-item specifies which data we want to access --

var navDataList = [
    { _tag: "CSidebarNavItem", name: "Data A", to: "/components" },
    { _tag: "CSidebarNavItem", name: "Data B", to: "/components" },
    .
    .
    .
    { _tag: "CSidebarNavItem", name: "Data Z", to: "/components" },
]

and they are created with this --

<CSidebarNav>
    <CCreateElement items={navDataList} components={{CSidebarNavItem}} />
</CSidebarNav>

So what I'm basically trying to do is to process data_A, data_B and data_C etc. using the same component Component1 when a user clicks the nav link Data A, Data B and Data C, respectively.

What I understood is that I have specify which data object I want to process inside the navList as a props. But I couldn't figure out how to that.

How do I solve this problem?

The documentations on CoreUI React components are here: CSidebarNavItem, CSidebarNav, CCreateElement.


A solution that somewhat works:

Inside the navDataList, if I specify these parameters, I can access from Component1:

var navDataList = [
    { _tag: "CSidebarNavItem", name: "Data A", 
        to: { 
            pathname: "/components",
            hash: "data_A_will_be_default",
            params: { data: "data_A" },
        },
    }, 
    { _tag: "CSidebarNavItem", name: "Data B", 
        to: { 
            pathname: "/components",
            hash: "data_B",
            params: { data: "data_B" },
        },
    }, 
    ...
];

and then identifying within Component1:

const Component1 = (props) => {
    var data = data_A; // default data to process
    if (props.location.params && props.location.params.data) {
        if (props.location.params.data === "data_B") {
            data = data_B;
        }
    }
    return(/* render component with data */);
}

But it's not responsive and there is a lag. The params.data doesn't update instantly.


Solution

  • I'd define a single "components" route path that takes the data as a route parameter and accessed in the Component1.

    Routes - define a path with route param "/components/:data"

    routes = [
      { path: "/components/:data", name: "Component1", component: Component1, }
      // there are more components but they are not relevant here.
    ];
    

    Links - link to a specific path with data specified

    var navDataList = [
      { _tag: "CSidebarNavItem", name: "Data A", to: "/components/A" },
      { _tag: "CSidebarNavItem", name: "Data B", to: "/components/B" },
      .
      .
      .
      { _tag: "CSidebarNavItem", name: "Data Z", to: "/components/Z" },
    ];
    

    Access match params via Route props or useParams react hook

    const Component1 = props => {
      const { data } = props.match.params;
      ...
    }
    

    or

    import { useParams } from 'react-router-dom';
    
    const Component1 = props => {
      const { data } = useParams();
      ...
    }