React parent is unmounted for child?

1k views Asked by At

I have a React Parent and Child component. The Child has to be able to update the state of the Parent component. However, I have the issue that my Parent is unmounted when the Child wants to update the Parent, and I'm not sure why or how to fix that?

I'm pasting the simplified code that is relevant to the issue. In this case, the child wants to update the page Title that is rendered in the Parent. But sadly, in the componentDidMount() of the Child (where this update happens) the Parent is already unmounted.

The index.js loads the Child directly but it wraps the Parent component around it. I guess that has something to do with the Parent component unmounting?

Parent:

type Props = TranslationProps & {
  Component: any
};
type State = {
  setTitle: string
};

export class Layout extends Component<Props, State> {
  _isMounted = false;

  constructor(props:Props) {
    super(props);

    this.state = {
      setTitle: ""
    };
  }

 componentDidMount() {
    this._isMounted = true;
  }

  componentWillUnmount() {
    this._isMounted = false;
  }

  render() {
    const { Component, ...restProps } = this.props;

    return (
      <Component
        setTitle={title=> this._isMounted && this.setState({ setTitle: title})}
        isMounted={this._isMounted}
        {...restProps}
      />
    );
  }
}

Child:

type Props = TranslationProps & {
  setTitle: (data: string) => void,
  isMounted: boolean
};

componentDidMount() {
    const { t } = this.props;
    if(this.props.isMounted) {
      this.props.setTitle("Test title");
    }
  }

Index:

const unwrap = component => {
  if(component.WrappedComponent) {
    return unwrap(component.WrappedComponent);
  }

  return component;
}

let reactMounts = document.querySelectorAll("[data-react]");
for (let reactMount of reactMounts) {
  let Component = Components[reactMount.dataset.react];
  let UnwrappedComponent = unwrap(Component);
  console.log("Rendering", Component, " (", UnwrappedComponent, ") to ", reactMount);

  let data = {
    ...reactMount.dataset,
    Component
  };
  delete data.react;

  render(
    React.createElement(Components['Layout'], data),
    reactMount
  );
}
1

There are 1 answers

1
Zero On
  • Reason: Accoring to React life-cycle, Child Component rendered before ComponentDidMount (where _isMounted = true). So, I guess the this._isMounted variable in setTitle props always = false => bug.

  • Solution: I recommend that you should create callback function in class, after that passing in setTitle props.