Experimental Fragment Flickering Streamlit Chart Elements

  1. Are you running your app locally or is it deployed?
    I am running the app locally on 1.36.0

When refreshing data inside an experiement_fragment with run_every parameter set, the visualisation will flicker (fade out / in) in line with the amount of time it takes to refresh/update the data.

In the example below you can simulate/adapt this behaviour by updating this section of code.

        # comment this line in/out to simulate expected/flickering behaviour
        import time
        time.sleep(3)

Is there anyway to avoid this flickering? In my real example, my update_data function takes about 1-2 second to check if new data exists/pull the data. In turn this means the plot fades in out (for a period of 1-2 seconds) every time the fragment re-runs (every 1 second.) This creates flicker, even though the data is not updating.

The flickering is independent on whether or not st.line_chart(data) is actually called. e.g. if you have some logic which says only call st.line_chart(data) if the data updates, the flickering still occurs.

The problem is not line_chart specific, I’ve tried with a few visual elements and I have the same problem.

import streamlit as st


from pages.example_components.datasets.example_data import ExampleData

import numpy as np
class ExampleData():
    def __init__(self):
        self.max_points = 50
        self.amplitude = 1
        self.frequency = 1
        self.phase_increment = 0.1
        self.x_values = np.linspace(0, 10, self.max_points)
        self.y_values = self.amplitude * np.sin(self.frequency * self.x_values)
        self.current_phase = 0

    def init_dataset(self):
        if self.name not in st.session_state:
            data = np.ones(30)
            st.session_state[self.name] = data
            return data
        else:
            data = st.session_state[self.name]
            return data

    def update_dataset(self):
        self.current_phase += self.phase_increment
        self.y_values = self.amplitude * np.sin(self.frequency * self.x_values + self.current_phase)
        return self.y_values


class ExamplePageRunner():
    def __init__(self):
        """Initialise all streamlit components and datasets components required to run page."""
        #  Set Page Config
        st.set_page_config(
            layout="wide",
            initial_sidebar_state="expanded",
        )
        # Init Components and Data
        self.extractor = ExampleData()
        self.line_chart_container = st.empty()

    def run(self):
        # Run Fragment to Refresh Data and Visualizations
        self.live_refresh()

    @st.experimental_fragment(run_every=1.0)
    def live_refresh(self):
        # Start Looping To Refresh Data and Visualizations
        data = self.extractor.update_dataset()  # Update Data

        # comment this line in/out to simulate expected/flickering behaviour
        import time
        time.sleep(3)

        # Render Line Chart in Container
        with self.line_chart_container:
            st.line_chart(data)


ExamplePageRunner().run()

This GIF shows the behaviour I’m describing - although the timing doesn’t quite align the the screen recording I took (3 seconds data update time.)
Screen Recording 2024-07-08 at 12.10.37

Is there a workaround for this? Or another way to structure the code to prevent this from happening?