Session state changes only after clicking button twice

I have to click the login button twice initially to show the welcome message


if 'username' not in st.session_state:
        st.session_state.username = ' '

if st.session_state.username:
    st.write('welcome ',st.session_state.username)
else:
    st.title('Login/Signup')
    email = st.text_input('Email')
    password = st.text_input('Password',type='password')
    if st.button('Login'):
            try:
                userinfo = sign_in_with_email_and_password(email,password)
                st.session_state.username = userinfo['username']
                st.session_state.useremail = userinfo['email']
                
            except:
                st.warning('Login Failed')

I am trying to create a login form. Once a person is logged in using correct user name and password, only then userinfo[‘username’] will contain a value. Not sure how to display the welcome message on the first button click itself. If I click the button twice, then it is working fine.

You can use st.rerun() if the log in succeeds, and that will run the page from top to bottom, and the welcome message will then be displayed properly.

            try:
                userinfo = sign_in_with_email_and_password(email,password)
                st.session_state.username = userinfo['username']
                st.session_state.useremail = userinfo['email']
                st.rerun()
            except:
                st.warning('Login Failed')

I have already tried it. st.rerun() fails inside the try except blocks.
Error:
RerunData(page_script_hash=‘d575aef6f69f53c7a18ce42c5b281cbb’, is_fragment_scoped_rerun=True)

Ah yes, I should have thought of that. The problem is that the way that st.rerun works is that it raises a special exception, and that tells Streamlit that it needs to rerun the page.

It’s a bad idea for this very reason (and others) to a “bare except” like try:....except: without any specific error (Avoid using bare except in Python - 30 seconds of code)

The best situation would be to figure out what sort of error the sign_in_with_email_and_password would raise, or just raise one yourself, and handle that specific error.

For example:

def sign_in_with_email_and_password(email, password):
    # Replace with real implementation
    if (email, password) not in get_logins():
        raise ValueError("Invalid login")

And then

try:
    userinfo = ...
    st.rerun()
except ValueError:
    st.warning("Login failed")
1 Like

Thanks a lot for the detailed explanation. It worked :grinning::+1:

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.