React js: component is not unmounted properly - reactjs

We have following scenario:
1. Parent component has child components.
==============================================================
<ContainerComponent>
<Layout>
<CustomComponent>
<ActualComponent>
<CustomComponent>
<ActualComponent>
==============================================================
This way component mounting takes place, and each ContainerComponent rendered according to task.
Component Container contain :
return (
<div className='row' >
<div className='col-md-12' >
<div className="ic-component" id="MainComponent" >
<div style={{'border':'5px;solid #e0e7f0'}}>
<div id="rootwizard3" className='wizard'>
<ul>
{TabHeader}
</ul>
<div className="tab-content" id="tabcontent" >
</div>
</div>
</div>
</div>
</div>
</div>
);
Then ContainerComponent contain Layout component :
$("#tabcontent").empty();
if(LayOut===null)
{
}
else {
React.render(
<div id={tabid}><div id={layoutid}>
<LayOut CurrentStepId={CurrentStepId} TaskDetails={TaskDetails} IsActualComponent="true"/>
</div>
</div>,document.getElementById('tabcontent'));
}
},
Layout component contains CustomComponent :
var findDiv1=$("div > #"+TabbId+" > div > div > div > div > div")[0];
$(findDiv1).empty();
var valueP3=1;
React.render(<CustomComponent inputType={Set} ItemName="" ItemId="" KeyValue={valueP3} addbtndispaly="" editbtndispaly="" deletebtndispaly="" Views="" />,findDiv1);
Unmounting of Container page:
React.unmountComponentAtNode(document.getElementById('tabcontent'));
Following way the components get mounted.
Initial component mounting. Here layout component loaded into Container Component. but custom component is not showing under Layout ? but output is poperly showing.
chrome react tool component loading structure
Second time component mounting, but here it only remove component under "ctab137". not unmounting custom component . Second copy of cutom component get created.
chrome react tool component loading structure-Second time loading
When we go to task(functionality) it mounts parent component and accordingly
respective child component gets mounted.
When we click to another task mean containerComponent then only containerComponent unmount get called. for that we are clearing container componenet div where its child componenet get mounted. and load another task child componenet.
But here is we are facing problem when we mount child componenet every times it get mounted separately if that component is already present. and that create problem. Here is above mentioned custom component is not get propely unmounted. Every time separate customComponent copy is created and that times that funtionality get executed.
Also here is child componenets componentWillUnmount not get called.
I want to know answers of following questions .
How to unmount child components if it is not unmounted ?
How to call child components unmount method if it's not called ?
Is there any way to unmount component by component name ?

Related

React JS - How to hide parent component content when child is rendering?

I have some nested components and I use outlet to render the children's content, but the page is getting crowded and I want to hide the parent content after the child is rendered . How can I do that?
let params = useParams();
<div>
!params.id && (<div>
*render your contents here* </div>)
<Outlet />
</div>
This should work , but where I have to put the code , in the parent component or in the child ?

How to open a new react component at the end of a stepper?

When I reach the end of my stepper component, how can I open a separate component that is decoupled from the stepper?
This is part of my react functional component which controls forward navigation. When I reach the 'Done' button, I want the component to open:
<ButtonContainer>
{activeStep !== 0 && (
<PrevButton onClick={handleBack}>Back</PrevButton>
)}
<NextButton
variant="contained"
color="primary"
onClick={handleNext}
>
{stepList && activeStep === stepList.length - 1
? 'Done'
: 'Next'}
</NextButton>
</ButtonContainer>
Is this something I would do in my handleNext function or do I create a separate function for this? Thanks in advance.
To open a decoupled component, you could use a Portal:
Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
What you would have to do is add another <div id="my-comp"/> somewhere next to your root div (<div id="root" />). Inside this div, the Portal will be rendered, instead of as normally as a descendant of the root div. The portal component would have to return something like this from it's render() function:
render() {
return ReactDOM.createPortal(
this.props.children,
myNode,
);
}
The first argument (this.props.children) is the component, which can be an element, string, or fragment, and the second argument (myNode) is a DOM element.
You can then import the Portal component in your react functional component and place it somewhere there. But it won't be rendered as child of that component thanks to the portal.
Check out this codepen for an example.
Regarding the done button. Either create a new function and use a ternary conditition in the onClick prop or add an if to handleNext.

When Reactjs has functional component as parent and child component as class

I am new in reactjs and learning bit and pieces. I am facing an issue. The scenario is like. I have a functional component as a parent. It has a child component as a class component. I would like to set or reset the child component's state on parent's button click. Or is there any way to call the child component's any method from the parent component. I tried as
// this call from a functional component.
<PhotoPreviewUploaend setSelectedFile={setSelectedFile} ref={setImagePreviewUrl} />
Later after a button click does this:-
setImagePreviewUrl('');
I read ref attribute allows access to the component. I tried this ref between 2 class component both parent and child is class components and it works as expected. But when did the same from a functional component it has no effect at all. How can I do it?
You are not embracing react one-way data flow by using refs like that; it might not behave the way you expect;
You should pass parent state handler logic function to the child component,
then child component call it with proper value; as the result your parent state will be updated and you have nice and clean one way data flow; you can use this in any kind of component, since you don't mess with this bindings in functional components;
This example demonstrates it in action:
function App() {
// Define your state
const [someState, setSomeState] = useState(0);
return (
<div className="container">
<Child parentCallback={setSomeState} />
</div>
);
}
class Child extends Component {
render(){
return(
<div>
<button
onClick={() => this.props.parentCallback(/*someValue*/)}
>
click me!
</button>
</div>
)
}
}

How to get react grand-child node to render when child is out of my control

I have a react component which uses a 3rd party library Component as a Child node. The Grand children (or the children of the 3rd party libary) are under my control. When my component receives new props it re-renders, however the 3rd party component seems to stop my components grand-children from re-rendering also, even though the props my component received, are passed to the non-re-rendering components directly
If I remove the 3rd party component then my component re-renders as do the grand-children.
render() {
<div>
<ThirdPartyComponent props={blah}>
{this.props.products.map(prod => <MyGrandChildrenComponents product={prod} />
</ThirdPartyComponent>
</div>
}
A concrete example can be found on this code sandbox: codesandbox.io/s/silly-grass-7frlx
I'd expect my MyGrandChildrenComponents component to get updated when this.props.products changes... Any hints?
This can happen if ThirdPartyComponent is a stateful component and is not handling its prop updates correctly. One way to force a re-render is to add a key prop to your ThirdPartyComponent and update its value when a re-render is needed.
render() {
<div>
<ThirdPartyComponent key={something-that-changes-when-rerender-needed} props={blah}>
{this.props.products.map(prod => <MyGrandChildrenComponents product={prod} />
</ThirdPartyComponent>
</div>
}
If ThirdPartyComponent is a PureComponent it should re render (and so re render its children) when one of its props changes so you can try:
render() {
<div>
<ThirdPartyComponent props={blah} products={this.props.products}>
{this.props.products.map(prod => <MyGrandChildrenComponents product={prod} />
</ThirdPartyComponent>
</div>
}
To trigger re renders when this.props.products changes.
But any prop should do.
If ThirdPartyComponent has a custom implementation of shouldComponentUpdate, then you will have to find the specific prop which triggers update if it exists.

What is causing my component to unmount?

I'm making an app where I have an Overlay component and a Map component rendering behind it just like this:
<div>
{showOverlay && <Overlay />}
<Map /> // this component should mount once
</div>
The overlay is shown to let the map load underneath but when I remove the Overlay (set showOverlay to false here) the Map component re-load.
At first I thought the Map component was just re-rendering, but after some digging I discovered that the component was actually re-mounting.
If I log in the componentWillMount, componentWillUnmount and render methods, the log appear in that order (which seems contradictory)
render
willUnmount
willMount
The parent does not re-mount, only the Map component do.
The Map component just render a div that reference a mapbox-gl-js map (like this https://gist.github.com/tristen/5c4b346ae38892f732504e6785d87057#file-map-js)
What can cause my component to re-mount itself like that ?
Thanks !

Resources