A way to reatin data_editor state across pages

to reatin state for normal component like st.selectbox, we can simply embed code below at the head of every page source script.

for i in st.session_state:
    st.session_state[i] = st.session_state[i]

However, when we encounter components like st.data_editor, an error come out, reads StreamlitAPIException: Values for st.button, st.download_button, st.file_uploader, st.data_editor, st.chat_input, and st.form cannot be set using st.session_state. We can handle this by following strategy

Step 1 store keys of st.data_editor in st.session_state.unsupported_keys in case reloading when switch pages

if 'unsupported_keys' not in st.session_state:
    st.session_state.unsupported_keys = []
for i in st.session_state:
    if i not in st.session_state.unsupported_keys:
        st.session_state[i] = st.session_state[i]

Step 2

  • store displayed data in st.session_state.df_types
  • store updated data in st.session_state.edited_df_types
  • store st.data_editor’s state in st.session_state.data_dtypes
# dataframe for data_editor to display in the first time
if 'df_types' not in st.session_state:
    st.session_state.df_types = df_types  
if 'edited_df_types' not in st.session_state:
    st.session_state.edited_df_types = df_types

data_dtypes_init = {'edited_rows': [],
                    'added_rows': [],
                    'deleted_rows': []}
if 'data_dtypes' not in st.session_state:
    st.session_state.data_dtypes = data_dtypes_init

Step 3 Exclude st.data_editor’s state from updating switching pages.

if 'data_dtypes' not in st.session_state.unsupported_keys:
    st.session_state.unsupported_keys.append('data_dtypes')

Step 4 update displayed data as updated data when switch back. the switch back motion can be recognized by whether st.session_state.data_dtypes was reset.

if st.session_state.data_dtypes == data_dtypes_init:
    st.session_state.df_types = st.session_state.edited_df_types.copy()  # update first time displayed dataframe

Step 5 set the displayed data as st.session_state.df_types.copy()

st.session_state.edited_df_types = st.data_editor(st.session_state.df_types.copy(), key='data_dtypes')

Then everything is done!

BUT! This solution is not perfect. the first time the script run, an error raised and click rerun will make everything right. The reason why rerun is needed still confuse me. I am waiting any answer for this topic