Home > Net >  How can I render one component conditionally twice and not lose internal states/unmounts?
How can I render one component conditionally twice and not lose internal states/unmounts?

Time:09-30

I have one component which needs to be rendered conditionally. Renders the same component with different styles. So, I did like this

import ComponentToRender from '../../ComponentToRender'

const Main =()=> {

const [expand,setExpand] =useState(false)

 return (
<div>
 {!expand  && <ComponentToRender {...someProps} />} 
 {expand && <div>
    <ComponentToRender {...otherProps} />
</div>
}
 <button onClick={()=>setExpand(pre => !pre)}>Expand</button>
</div>

 
)
}

For the above code, I get what I want in terms of UI. But, all the internal states are lost. I must render two components like that and keep the internal states. Is that possible to do that in React?

CodePudding user response:

You can achieve this by keeping the component rendered unconditionally and hiding it with CSS.
You get to preserve Component‘s state for free along with the DOM state (scroll, focus, and input position). However, this solution has drawbacks, too:

  • You mount the component on startup, even if the user never accesses it.
  • You update the component even when it’s invisible.
import ComponentToRender from "../../ComponentToRender";

const Main = () => {
  const [expand, setExpand] = useState(false);

  return (
    <div>
      <div style={{ display: expand ? null : "none" }}>
        <ComponentToRender {...someProps} />
      </div>
      <div style={{ display: !expand ? null : "none" }}>
        <div>
          <ComponentToRender {...otherProps} />
        </div>
      </div>{" "}
      <button onClick={() => setExpand((pre) => !pre)}>Expand</button>
    </div>
  );
};

CodePudding user response:

The reconciliation algorithm is such that when on next render you move from one component to component of different type (assuming they have same spot in component hierarchy), instance of old component is destroyed.

Since you have <ComponentToRender/> and another one is <div><ComponentToRender/></div>, they are different components (because one is inside a div).

Read about reconciliation.

What you can do is move the state of ComponentToRender to Main and pass it as props. Now even if the component unmounts the state will not be lost.

  • Related