Dynamically import component in React based on config entries












2














I have multiple apps as part of one React-redux-typescript project. All of these individual apps are part of a core-application. I want to dynamically set up routing.



My current routes look like this:



Routes.tsx



import HomePageApp  from "../Components/Home/HomeApp";
import TestApp from "../Components/Test/TestApp";
export default function Routes() {
return (
<Switch>
<RedirectIfAuthenticated
exact={true}
isAuthenticated={true}
path={Path.homePath} --> "/"
component={HomePage} ---> AppName coming from import statement on top
redirectPath={Path.homePath} --> "/"
/>
<RedirectIfAuthenticated
isAuthenticated={true}
path={Path.apps.test} --> "/test"
component={TestApp} --> AppName from import on top
redirectPath={Path.homePath} --> "/"
/>
</Switch>
);
}


And RedirectIfAuthenticated simply redirects to correct applications' landing pages.



RedirectIfAuthenticated.tsx



export default function RedirectIfAuthenticated({
component,
redirectPath,
isAuthenticated,
...rest
}: IRedirectIfAuthenticatedProps) {
const Component = component;
const render = (renderProps: RouteComponentProps<any>) => {
let element = <Component {...renderProps} />;
return element;
};

return <Route {...rest} render={render}/>;
}


I've a config file like this:



Manifest.ts



export let manifest = {
apps: [
{
componentPath: "/Test/App",
path: "/test",
name: "Test"
},
...more objects for other apps
]
};


In my Routes.tsx, I want to make use of my manifest to render the RedirectIfAuthenticated component.



so I can figure out this change:



for brevity showing the dirty approach but the actual code iterates over the manifest using .map and renders RedirectIfAutenticated.



const app = manifest.apps.find(app => app.name === "Test");
<Switch>
<RedirectIfAuthenticated
isAuthenticated={true}
path={app.path} --> "/test"
component={What should I do here? How to pass component reference by path??}
redirectPath={"/"} ==> I typically get this from my manifest..
/>
</Switch>


One option is to do this:



component={require("path from manifest").default}


but our tslint throws a bunch of errors at this. Other than this I can't figure out how to pass the component reference here dynamically. Looking for a better approach.



The Routes.tsx needs to be dynamic so that adding new apps is a matter of configuration so I can't do imports on top because I dont know what's gonna be added in config. Thanks.










share|improve this question
























  • If your React version is v16.6.x then you can try to use React.lazy doing something like component={React.lazy(() => import("path from manifest"))} <- you don't need to extract .default with lazy as it's done automatically. Also refer to my Shameless Plug: Loading React Components Dynamically on Demand
    – Sung Kim
    Nov 20 at 19:12


















2














I have multiple apps as part of one React-redux-typescript project. All of these individual apps are part of a core-application. I want to dynamically set up routing.



My current routes look like this:



Routes.tsx



import HomePageApp  from "../Components/Home/HomeApp";
import TestApp from "../Components/Test/TestApp";
export default function Routes() {
return (
<Switch>
<RedirectIfAuthenticated
exact={true}
isAuthenticated={true}
path={Path.homePath} --> "/"
component={HomePage} ---> AppName coming from import statement on top
redirectPath={Path.homePath} --> "/"
/>
<RedirectIfAuthenticated
isAuthenticated={true}
path={Path.apps.test} --> "/test"
component={TestApp} --> AppName from import on top
redirectPath={Path.homePath} --> "/"
/>
</Switch>
);
}


And RedirectIfAuthenticated simply redirects to correct applications' landing pages.



RedirectIfAuthenticated.tsx



export default function RedirectIfAuthenticated({
component,
redirectPath,
isAuthenticated,
...rest
}: IRedirectIfAuthenticatedProps) {
const Component = component;
const render = (renderProps: RouteComponentProps<any>) => {
let element = <Component {...renderProps} />;
return element;
};

return <Route {...rest} render={render}/>;
}


I've a config file like this:



Manifest.ts



export let manifest = {
apps: [
{
componentPath: "/Test/App",
path: "/test",
name: "Test"
},
...more objects for other apps
]
};


In my Routes.tsx, I want to make use of my manifest to render the RedirectIfAuthenticated component.



so I can figure out this change:



for brevity showing the dirty approach but the actual code iterates over the manifest using .map and renders RedirectIfAutenticated.



const app = manifest.apps.find(app => app.name === "Test");
<Switch>
<RedirectIfAuthenticated
isAuthenticated={true}
path={app.path} --> "/test"
component={What should I do here? How to pass component reference by path??}
redirectPath={"/"} ==> I typically get this from my manifest..
/>
</Switch>


One option is to do this:



component={require("path from manifest").default}


but our tslint throws a bunch of errors at this. Other than this I can't figure out how to pass the component reference here dynamically. Looking for a better approach.



The Routes.tsx needs to be dynamic so that adding new apps is a matter of configuration so I can't do imports on top because I dont know what's gonna be added in config. Thanks.










share|improve this question
























  • If your React version is v16.6.x then you can try to use React.lazy doing something like component={React.lazy(() => import("path from manifest"))} <- you don't need to extract .default with lazy as it's done automatically. Also refer to my Shameless Plug: Loading React Components Dynamically on Demand
    – Sung Kim
    Nov 20 at 19:12
















2












2








2







I have multiple apps as part of one React-redux-typescript project. All of these individual apps are part of a core-application. I want to dynamically set up routing.



My current routes look like this:



Routes.tsx



import HomePageApp  from "../Components/Home/HomeApp";
import TestApp from "../Components/Test/TestApp";
export default function Routes() {
return (
<Switch>
<RedirectIfAuthenticated
exact={true}
isAuthenticated={true}
path={Path.homePath} --> "/"
component={HomePage} ---> AppName coming from import statement on top
redirectPath={Path.homePath} --> "/"
/>
<RedirectIfAuthenticated
isAuthenticated={true}
path={Path.apps.test} --> "/test"
component={TestApp} --> AppName from import on top
redirectPath={Path.homePath} --> "/"
/>
</Switch>
);
}


And RedirectIfAuthenticated simply redirects to correct applications' landing pages.



RedirectIfAuthenticated.tsx



export default function RedirectIfAuthenticated({
component,
redirectPath,
isAuthenticated,
...rest
}: IRedirectIfAuthenticatedProps) {
const Component = component;
const render = (renderProps: RouteComponentProps<any>) => {
let element = <Component {...renderProps} />;
return element;
};

return <Route {...rest} render={render}/>;
}


I've a config file like this:



Manifest.ts



export let manifest = {
apps: [
{
componentPath: "/Test/App",
path: "/test",
name: "Test"
},
...more objects for other apps
]
};


In my Routes.tsx, I want to make use of my manifest to render the RedirectIfAuthenticated component.



so I can figure out this change:



for brevity showing the dirty approach but the actual code iterates over the manifest using .map and renders RedirectIfAutenticated.



const app = manifest.apps.find(app => app.name === "Test");
<Switch>
<RedirectIfAuthenticated
isAuthenticated={true}
path={app.path} --> "/test"
component={What should I do here? How to pass component reference by path??}
redirectPath={"/"} ==> I typically get this from my manifest..
/>
</Switch>


One option is to do this:



component={require("path from manifest").default}


but our tslint throws a bunch of errors at this. Other than this I can't figure out how to pass the component reference here dynamically. Looking for a better approach.



The Routes.tsx needs to be dynamic so that adding new apps is a matter of configuration so I can't do imports on top because I dont know what's gonna be added in config. Thanks.










share|improve this question















I have multiple apps as part of one React-redux-typescript project. All of these individual apps are part of a core-application. I want to dynamically set up routing.



My current routes look like this:



Routes.tsx



import HomePageApp  from "../Components/Home/HomeApp";
import TestApp from "../Components/Test/TestApp";
export default function Routes() {
return (
<Switch>
<RedirectIfAuthenticated
exact={true}
isAuthenticated={true}
path={Path.homePath} --> "/"
component={HomePage} ---> AppName coming from import statement on top
redirectPath={Path.homePath} --> "/"
/>
<RedirectIfAuthenticated
isAuthenticated={true}
path={Path.apps.test} --> "/test"
component={TestApp} --> AppName from import on top
redirectPath={Path.homePath} --> "/"
/>
</Switch>
);
}


And RedirectIfAuthenticated simply redirects to correct applications' landing pages.



RedirectIfAuthenticated.tsx



export default function RedirectIfAuthenticated({
component,
redirectPath,
isAuthenticated,
...rest
}: IRedirectIfAuthenticatedProps) {
const Component = component;
const render = (renderProps: RouteComponentProps<any>) => {
let element = <Component {...renderProps} />;
return element;
};

return <Route {...rest} render={render}/>;
}


I've a config file like this:



Manifest.ts



export let manifest = {
apps: [
{
componentPath: "/Test/App",
path: "/test",
name: "Test"
},
...more objects for other apps
]
};


In my Routes.tsx, I want to make use of my manifest to render the RedirectIfAuthenticated component.



so I can figure out this change:



for brevity showing the dirty approach but the actual code iterates over the manifest using .map and renders RedirectIfAutenticated.



const app = manifest.apps.find(app => app.name === "Test");
<Switch>
<RedirectIfAuthenticated
isAuthenticated={true}
path={app.path} --> "/test"
component={What should I do here? How to pass component reference by path??}
redirectPath={"/"} ==> I typically get this from my manifest..
/>
</Switch>


One option is to do this:



component={require("path from manifest").default}


but our tslint throws a bunch of errors at this. Other than this I can't figure out how to pass the component reference here dynamically. Looking for a better approach.



The Routes.tsx needs to be dynamic so that adding new apps is a matter of configuration so I can't do imports on top because I dont know what's gonna be added in config. Thanks.







reactjs typescript ecmascript-6 import router






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 at 19:00

























asked Nov 20 at 18:30









clever_bassi

1,34721033




1,34721033












  • If your React version is v16.6.x then you can try to use React.lazy doing something like component={React.lazy(() => import("path from manifest"))} <- you don't need to extract .default with lazy as it's done automatically. Also refer to my Shameless Plug: Loading React Components Dynamically on Demand
    – Sung Kim
    Nov 20 at 19:12




















  • If your React version is v16.6.x then you can try to use React.lazy doing something like component={React.lazy(() => import("path from manifest"))} <- you don't need to extract .default with lazy as it's done automatically. Also refer to my Shameless Plug: Loading React Components Dynamically on Demand
    – Sung Kim
    Nov 20 at 19:12


















If your React version is v16.6.x then you can try to use React.lazy doing something like component={React.lazy(() => import("path from manifest"))} <- you don't need to extract .default with lazy as it's done automatically. Also refer to my Shameless Plug: Loading React Components Dynamically on Demand
– Sung Kim
Nov 20 at 19:12






If your React version is v16.6.x then you can try to use React.lazy doing something like component={React.lazy(() => import("path from manifest"))} <- you don't need to extract .default with lazy as it's done automatically. Also refer to my Shameless Plug: Loading React Components Dynamically on Demand
– Sung Kim
Nov 20 at 19:12














1 Answer
1






active

oldest

votes


















0














I was able to use dynamic imports to achieve this. I used this article to understand a few concepts.



 private loadComponentFromPath(path: string) {
import(`../../ScriptsApp/${path}`).then(component =>
this.setState({
component: component.default
})
);
}


One important distinction here is if I don't give the path from the root of the app, I get an error saying "Unable to find the module". This is why I've given the full path from the root.






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53399332%2fdynamically-import-component-in-react-based-on-config-entries%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    I was able to use dynamic imports to achieve this. I used this article to understand a few concepts.



     private loadComponentFromPath(path: string) {
    import(`../../ScriptsApp/${path}`).then(component =>
    this.setState({
    component: component.default
    })
    );
    }


    One important distinction here is if I don't give the path from the root of the app, I get an error saying "Unable to find the module". This is why I've given the full path from the root.






    share|improve this answer


























      0














      I was able to use dynamic imports to achieve this. I used this article to understand a few concepts.



       private loadComponentFromPath(path: string) {
      import(`../../ScriptsApp/${path}`).then(component =>
      this.setState({
      component: component.default
      })
      );
      }


      One important distinction here is if I don't give the path from the root of the app, I get an error saying "Unable to find the module". This is why I've given the full path from the root.






      share|improve this answer
























        0












        0








        0






        I was able to use dynamic imports to achieve this. I used this article to understand a few concepts.



         private loadComponentFromPath(path: string) {
        import(`../../ScriptsApp/${path}`).then(component =>
        this.setState({
        component: component.default
        })
        );
        }


        One important distinction here is if I don't give the path from the root of the app, I get an error saying "Unable to find the module". This is why I've given the full path from the root.






        share|improve this answer












        I was able to use dynamic imports to achieve this. I used this article to understand a few concepts.



         private loadComponentFromPath(path: string) {
        import(`../../ScriptsApp/${path}`).then(component =>
        this.setState({
        component: component.default
        })
        );
        }


        One important distinction here is if I don't give the path from the root of the app, I get an error saying "Unable to find the module". This is why I've given the full path from the root.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 30 at 23:04









        clever_bassi

        1,34721033




        1,34721033






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53399332%2fdynamically-import-component-in-react-based-on-config-entries%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Create new schema in PostgreSQL using DBeaver

            Deepest pit of an array with Javascript: test on Codility

            Costa Masnaga