Home > database >  How to render a component outside the component that contains the function that renders the first co
How to render a component outside the component that contains the function that renders the first co

Time:10-30

The situation is a bit complicated:

  • inside a component called "LeftSectionHeader" I have a div, which when clicked must render a component;

  • the component to be rendered is called "ProfileMenu", and is basically a div that must be rendered on top of "LeftSectionHeader" itself and another div;

  • All these components are rendered inside another component called "Main".

The problem is that if I define the function inside "LeftSectionHeader", "ProfileMenu" will be rendered inside, while I need it to not only be rendered outside, but even cover it; that's why you'll see some boolean vars inside "Main", because that is the only way i could render it, but it still doesn't cover the other divs. I'll attach the code of each component and how the final result should look below.

LeftSctionHeader:

 function LeftSectionHeader(){
  return(
    <div class="left-section-header">
        <div class="crop" ><img src="./images/profiles/anonimous.png" /></div>
    </div>
  );
}

The div belonging to the "crop" class is the one that must be clicked to render "ProfileMenu"

ProfileMenu:

   function ProfileMenu(){
  
  return(
    <div class="profile-side-menu">
       //A lot of boring stuff
    </div>
  );
}

There are some functions related to this component, but they are not important, so I didn't put them, just ignore it

Main:

var p=true;
var m=true;

    function Main(){
      return(
        <div class="main">
          <Header />
            <div class="left-section">
            {m ? <div><LeftSectionHeader /><LangMenu /></div>  : <ProfileMenu />}
            </div>
          {p ? <PostPage /> : <NoPostsMessage />} //Ignore this line
          </div>
      );
    }

Before clicking on the orange div

After clicking

CodePudding user response:

This might help as guidline, hopefully!

function LeftSectionHeader({ onClick }){
  return(
    <div class="left-section-header" onClick={onClick}>
        <div class="crop" ><img src="./images/profiles/anonimous.png" /></div>
    </div>
  );
}

function Main(){
  const [showProfile, setShowProfile] = useState(false);

  return(
    <div class="main">
      <Header />
        <div class="left-section">
          {!showProfile ? (
            <div>
              <LeftSectionHeader onClick={() => setShowProfile(true)} />
              <LangMenu />
            </div>
          )  : <ProfileMenu />}
        </div>
        {p ? <PostPage /> : <NoPostsMessage />} //Ignore this line
      </div>
  );
}
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

The simplest solution might be to pass a handler into the header component to toggle the menu:

function App () {
  const [showMenu, setShowMenu] = useState();
  return (
    <div>
      <Header onMenuToggle={() => setShowMenu(!showMenu)} />
      { showMenu && <Menu /> }
    </div>
  )
}

function Header ({ onMenuToggle }) {
    <div onClick={onMenuToggle}>...</div>
}

Caveat: This will cause the entire App component to re-render when the menu state changes. You can mitigate this by either

  • A) placing the menu state closer to where it's actually needed, like in the sidebar component instead of at the top, or
  • B) using a context or other orthogonal state store.

Another approach would be to leave the state handling in the LeftSectionHeader component and then use a React portal to render the menu elsewhere in the DOM.

  • Related