Mir
Mir

Reputation: 75

How is componentDidMount used even after state is changed?

I was learning React and came across this code:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

The question is how is componentDidMount called even after state gets changed, that is,

componentDidMount() {
        this.timerID = setInterval(
          () => this.tick(),
          1000
        );
      }

in right above code setInterval is called which in turn calls tick function that changes state. But after the state changes and after the component is re-rendered, is componentDidMount called again?

Upvotes: 0

Views: 152

Answers (3)

Shravan Dhar
Shravan Dhar

Reputation: 1560

No you're mistaken, the componentDidMount is called only once after render, it's the tick function which is called again and again after every second. Let me elaborate:

After render ->

  1. componentDidMount is called. Inside it the setInterval get called.
  2. setInterval gets queued in the event queue, returns an id (a number) to this.timerID and componentDidMount exits.
  3. The tick function is pushed to the stack and executed after one second duration.
  4. Since it's a setInterval, it's there in the queue and again gets executed after one second.
  5. Pattern is followed...

I understand that you're confused as to how the tick is called again and again and not the componentDidMount. See the following:

fuction parentFunction() {
  setInterval(() => {
    childFunction();
  }, 1000);
}

parentFunction();

In ths scenario, the childFunction is inside the setInterval (the parentFunction is not) and hence only childFunction is called again and again, and not the parentFunction.

Hope it helps :)

Upvotes: 1

HMR
HMR

Reputation: 39270

A component will mount when it's rendered for the first time or after an unmount or when you change the key prop.

So if you have a component named WillSometimesRender it will unmount when it was rendered before but is not rendered now.

And if you have a component named KeyChange it will unmount when rendered with a different key and then remount (see code below)

class KeyChange extends React.Component {
  componentDidMount() {
    console.log('key change got mounted');
  }
  componentWillUnmount() {
    console.log('key change got unmounted');
  }
  render() {
    return <div>key change</div>;
  }
}
class WillSometimesRender extends React.Component {
  componentDidMount() {
    console.log('will sometimes render got mounted');
  }
  componentWillUnmount() {
    console.log('will sometimes render got unmounted');
  }
  render() {
    return <div>will sometimes render</div>;
  }
}
const App = () => {
  const [key, setKey] = React.useState(1);
  return (
    <div>
      <button onClick={() => setKey(key => key + 1)}>
        Change key
      </button>
      <KeyChange key={key} />
      {key % 2 && <WillSometimesRender />}
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Upvotes: 0

Jai
Jai

Reputation: 74738

is componentDidMount called again?

No, it won't be called again. In a component render componentDidMount gets called once on the first render only. If you need to get the previous value again there is another lifecycle method for this componentDidUpdate. Something like:

componentDidUpdate(prevProps, prevState){
    console.log(prevState);
}

Upvotes: 1

Related Questions