Bi-directional component lifecycle | Experiment

Summary

Hi, I am exploring the behavior of the by-directional custom component and would like to share with the community.
I also got some questions and would be happy that some could advise me on them.

Starting from the template at component-template/template at master · streamlit/component-template · GitHub, I have added several console.log calls so that the component lifecycle becomes clear.

Steps to reproduce

My script is at GitHub - kota7/streamlit-custom-component-experiment.
Essentially, I added the following lines to the template:

  constructor(prop: any) {
    super(prop)
    console.log("constructor!")
  }
  public componentDidMount() { 
    console.log("Component did mount!");
    Streamlit.setFrameHeight(); 
  }
  public componentDidUpdate() {
     console.log(String(this.state.numClicks), "Component did update!");
     const x = document.getElementById("hoge")
     if (x != null) { x.innerHTML = String(this.state.numClicks) }
     Streamlit.setFrameHeight();
  }
  public componentWillUnmount() {
    console.log("Component will mount!"); 
    Streamlit.setFrameHeight(); 
  }

You can reproduce this locally by the steps described at Components API - Streamlit Docs.

Observations

I got the following observations:

  • On the first run, we have two constructor calls, followed by two render calls, followed by one componentDidMount call.
  • When I click the button, we have ( two render calls, followed by one componentDidUpdate call ), and this is repeated twice.
constructor!
constructor!
Render!
Render!
0 Component did mount!
Render!
Render!
0 Component did update!
Render!
Render!
1 Component did update!
Render!
Render!
1 Component did update!
Render!
Render!
2 Component did update!
Render!
Render!
2 Component did update!
...

simplescreenrecorder-2022-11-14_20.03.26

Questions:

  1. I wonder why there are constructor and render are called twice. Is this due to React, or streamlit design?
  2. I also wonder why componentDidUpdate is called twice.

It will be great if you could give me some internal workings on this behavior. Thanks!

Have you tried with setFrameHeight called only once, in componentDidMount?

I think that’s called only once already. Did I miss something?