Saturday, 27 February 2021

Prevent child component from unmounting and remounting if parent component changes

Problem:

In the code below, when the Toggle ParentA/B button is clicked, the <Child /> component will be unmounted and remounted again, only though effectively only the Parent component changed.

How do I prevent Child from unmounting and remounting in such a situation?

import React, { useState } from "react"

const App = () => {
    const [a, setA] = useState(true)
    return (
        <div>
            <button onClick={() => setA(!a)}>Toggle ParentA/B</button>
            {a ? <ParentA><Child /></ParentA> : <ParentB><Child /></ParentB>}
        </div>
    )
}
const ParentA = ({ children }) => <div>parentA{children}</div>
const ParentB = ({ children }) => <div>parentB{children}</div>

class Child extends React.Component {
    componentDidMount() {
        console.log('child did mount')
    }

    componentWillUnmount() {
        console.log('child will unmount')

    }

    render() {
        return (
            <div>child</div>
        )
    }

}

export default App

Replies to potential answers:

Why not just let the Child component remount since it's only a <div> element?

Normally this wouldn't matter if the Child component renders cheaply. However, in my case, the Child component takes very long to mount, so I cannot afford a remounting every time the Parent component changes.

You could pass the parentA or parentB string as props to a generic Parent component.

const App = () => {
    const [a, setA] = useState(true)
    return (
        <div>
            <button onClick={() => setA(!a)}>Toggle ParentA/B</button>
            <ParentGeneric content={a? 'parentA': 'parentB'}><Child /></ParentGeneric>
        </div>
    )
}
const ParentGeneric = ({children, content}) => <div>{content}{children}</div>

class Child extends React.Component {
    ...
}

This would work. Unfortunately, this restricts my Parent component's JSX structure to be identical. In other words, if my ParentA and ParentB's JSX structure were different, then I'm not sure how to pass the difference as props.

For example:

const ParentA = ({ children }) => <div><div><h1>parentA{children}</h1></div></div>
const ParentB = ({ children }) => <div>parentB{children}</div>

If parentA and parentB are defined this way, would it still be possible to abstract these two components into a ParentGeneric component and simply passing the structural difference between ParentA and ParentB as props?



from Prevent child component from unmounting and remounting if parent component changes

No comments:

Post a Comment