Streamlit 0.84+ widgets are copying selected option values, breaking things

I posted this issue as streamlit/streamlit#3703 last week, but it hasn’t gotten any attention. In short, Streamlit 0.84 changed the behaviour of widgets that work with a list of options by copying the selected option values instead of holding the values as is. I really want to use the new session state APIs in 0.84+, but this change in the widgets is breaking too many other things. Has anyone else encountered this issue? Any suggestions?

Here’s a code example. If you pass an list of options that aren’t simple scalar values to a st.selectbox, the selectbox copies the select option, resulting in Streamlit silently failing (0.84 and 0.85) or raising a ValueError (0.86) because the selected value isn’t in the list of options, due to copying.

import streamlit as st

class Thing(object):
    pass

st.text(f"Streamlit {st.__version__}")

options = [("Option 1", Thing()), ("Option 2", Thing())]
st.text(options[0])
st.text(options[1])

option = st.selectbox("Options:", options, format_func=lambda c: c[0])
st.text(option)

The same problem occurs in related widgets like st.radio or st.multiselect.