Bug (?) preventing iteration over displayed elements with recursive function

Hi! I’m trying to have page elements in an iterable display element by element until a user is done. I’ve implemented this with a recursive function, that I’ve simplified here:

def write_i(i):
    st.write(i)
    if i == 5:
        return
    if st.button('Next?', key=i):
        i += 1
        write_i(i)

If I call write_I(0), I’d expect 0 to print and the button ‘Next?’ to appear then, on clicking, for 1 to appear and the button, and so on until 5 is printed.

It seems to work for the first two iterations: I see 0, Next? then '1, Next?` – but on clicking that ‘Next’ button, the page starts again at 0.

Am I missing something? Thanks!

Hi @paulwcoles, welcome to the Streamlit community!

This isn’t a bug per se, but a reflection of how the Streamlit evaluation model works. I’ve briefly written about that design decision here:

What is happening is that within your recursive function, you are calling a Streamlit widget (st.button), which is then re-running Streamlit from the top of your script. So instead of getting the behavior you are expecting, you are seeing the code be re-run and the state being lost.

As part of our 2021 roadmap, we’re working on a robust state management functionality, but in the meantime, you can take a look at the following example about maintaining state between runs. If you persist your variable i in state across runs, I think you should get the behavior you are looking for.

Best,
Randy

1 Like

That makes sense – I hadn’t thought about it as a stateless app. I’ll implement something similar to the SessionState class you referenced.

Thanks so much for the help – I’m new to it, but loving Streamlit!

1 Like