skip to Main Content

I got a problem and can’t find the solution. Sorry if it’s a dumb one but I’m a newby with React.

I want to dynamically load a component inside useEffect hook. I can load the file but cant access the function.

Here is my main file

footer.js

import React, { useEffect, useState}  from "react";

const MyMainComponent = ({ type }) => {

const [preFooter,setPreFooter ] = useState(null)

useEffect(() => {
    if (type === "page") {
      import( "./prefooter/preFooterPage")
      .then(PreFooterPage =>
       setPreFooter(result)
      );
    } else {
      import( "./prefooter/preFooterArticle")
      .then(x =>
        setPreFooter(result)
      );
    }
  }, [type]);

return (
//I want to use the result like this : <preFooter/>
...
)

}

export default MyMainComponent

Here are the two different components :

preFooterArticle.js

import React from "react";

const PreFooterArticle = () => {

return (
<h2>Hi, I'm a pre Footer for blog posts !</h2>
)

}

export default PreFooterArticle

preFooterPage.js

import React from "react";

const PreFooterPage = () => {

return (
<h2>Hi, I'm a pre Footer for pages !</h2>
)

}

export default PreFooterPages

The import and set state work fine but I dont know how return the state as a component ?

Thanks a lot for your help

2

Answers


  1. If you want to return a state as a component use redux.

    https://redux.js.org/tutorials/essentials/part-1-overview-concepts

    Redux is more useful when:

    You have large amounts of application state that are needed in many
    places in the app.
    The app state is updated frequently over time.
    The
    logic to update that state may be complex.
    The app has a medium or
    large-sized codebase, and might be worked on by many people

    As example, the index.js should look like this:`import React from

    import ReactDOM from 'react-dom/client';
    import './index.css';
    import App from './App';
    import reportWebVitals from './reportWebVitals';
    import { BrowserRouter } from 'react-router-dom';
    import {Provider} from 'react-redux';
    
    import {StrictMode} from 'react';
    import {createRoot} from 'react-dom/client';
    
    
    
    
    
    import store from './redux/redux-store'
    
    const rootElement = document.getElementById('root');
    const root = createRoot(rootElement);
    
    
    
    let rerenderEntireTree = (state) => {
    
      console.log(state)
      root.render(
          <BrowserRouter>
            <Provider store={store}>
              <App state={state} dispatch={store.dispatch.bind(store)} store={store}/>
            </Provider>
          </BrowserRouter>, document.getElementById('root')
      )
    
    }
    
    rerenderEntireTree(store.getState())
    store.subscribe(() => {
      let state = store.getState()
      rerenderEntireTree(state)
    
    })`
    

    The rerenderEntireTree function helps to rerender as the state changes as well as subscribe

    and create reducer files as for example this:

    let initialState = {
        sidebar: {}
    }
    
    const sidebarReducer = (state = initialState, action) => {
    
        
        return state;
    }
    
    export default sidebarReducer
    
    Login or Signup to reply.
  2. Before the dynamic import is loaded, you need to supply a default component state (() => null), since useState treats any functions passed in init as initializer, you’ll need to wrap it in another function (() => () => null).

    When you import a file, you get an object, with the actual imports as properties of the object, so you need to extract your component ({ default: comp }). Then you set it on your state, and again need to wrap it with a function, so it won’t be treated as an updater functionsetPreFooter(() => comp).

    Code (Sandbox):

    const MyMainComponent = ({ type }) => {
      const [PreFooter, setPreFooter] = useState(() => () => null); // default state should be a component that renders null
    
      useEffect(() => {
        const url =
          type === 'page'
            ? './prefooter/preFooterPage'
            : './prefooter/preFooterArticle';
    
        import(url).then(
          (
            { default: comp } // get the import from the returned object
          ) => setPreFooter(() => comp) // use updater function to set in state
        );
      }, [type]);
    
      return <PreFooter />;
    };
    

    However, instead of inventing the wheel, you can use React.lazy to load the component dynamically, and wrap it with to provide a fallback until the component is loaded.

    Code (sandbox):

    import React, { lazy, Suspense } from 'react';
    
    const PreFooterPage = lazy(() => import('./prefooter/preFooterPage'));
    const PreFooterArticle = lazy(() => import('./prefooter/preFooterArticle'));
    
    const MyMainComponent = ({ type }) => (
      <Suspense fallback="Loading">
        {type === 'page' ? <PreFooterPage /> : <PreFooterArticle />}
      </Suspense>
    );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search