Mas Bagol Mas Bagol - 3 months ago 16
React JSX Question

Why componentDidMount in higher order component called more than once?

The docs says:


Invoked once, only on the client (not on the server), immediately
after the initial rendering occurs.


Now, when I try to create a higher order component:

import React from 'react';
import { connect } from 'react-redux';

function wrap(Wrapped) {

class Wrapper extends React.Component {
componentDidMount() {
// I will place some reusable functionality here which need to
// be called once on mounted.
console.log('wrapper component mounted');
}
render() {
return <Wrapped {...this.props}/>
}
}
return Wrapper;
}

class Wrapped extends React.Component {
componentDidMount() {
console.log('wrapped component mounted');
}
render() {
return <div></div>;
}
}

connect()(wrap(Wrapped));


Now, every time any changes occur in props, the console will print this:

'wrapped component mounted'
'wrapper component mounted'


If I remove the
Wrapper
, it will only print this once (when mounted
in the first time):

`wrapped component mounted`


So, Why componentDidMount in higher order component called more than once?

Answer

connect()(wrap(Wrapper)); <-- replace with Wrapped

I have tested it. And it works.

function wrap(Wrapped) {
  class Wrapper extends React.Component {
    componentDidMount() {
      console.log('wrapper component mounted');
    }
    render() {
      return <Wrapped {...this.props}/>
    }
    componentDidUpdate(prevProps, prevState){
        console.log(this.props);
    }
  }
  return Wrapper;
}
class Wrapped extends React.Component {
  componentDidMount() {
    console.log('wrapped component mounted');
  }
  componentDidUpdate(prevProps, prevState){
      console.log(this.props);
  }
  render() {
    return <div></div>;
  }
}

connect(state=>({state}))(wrap(Wrapped));

wrap func returns Wrapper, you can't pass the Wrapper into wrap func. it's loop