Handling Page Transitions in Streamlit: A Practical Guide
In building interactive web applications, managing page transitions smoothly is crucial for enhancing user experience. Recently, I developed a Streamlit application called Job Search Sculptor, that combines crucial job searching steps together. One of the challenges I faced was handling page transitions effectively. In this article, I’ll walk you through how I managed page transitions using Streamlit's session state and buttons.
Application Overview
My application has three main stages:
- Setup Tab: Users provide search parameters, filters and upload their resumes.
- Scraper Tab: The application scrapes job listings based on the provided search parameters and presents them to user to reject or pick best-fitting resumes of theirs
- Result Tab: Users view the results, save as csv file and generate cover letters.
Handling Page Transitions
Main Function
The main function initializes the session state and controls the flow between different tabs.
def main():
if st.session_state.get("setup_tab") == None:
st.session_state["setup_tab"] = True
if st.session_state.get("setup_tab"):
setup_tab()
elif st.session_state.get("scraper"):
with st.spinner("Scraping..."):
data = scraper.scrape(st.session_state["search_term"],
st.session_state["results_wanted"],
st.session_state["hours_old"],
st.session_state["offset"])
st.session_state["data"] = data
st.session_state["scraper"] = False
st.session_state["scraper_tab"] = True
st.rerun()
elif st.session_state.get("scraper_tab"):
scraper_tab()
elif st.session_state.get("result_tab"):
result_tab()
The crux of the application lies in handling the transitions between these tabs. This is managed using Streamlit’s session state and conditional checks within the main
function.
Setup Tab
In the setup_tab
function, user inputs are collected. Once the user completes the setup and clicks the "Proceed to Scraper" button, the session state is updated and st.rerun()
is called to refresh the page and move to the next step.
import os
import streamlit as st
def setup_tab():
st.title("Setup")
#setup widgets
if st.button("Proceed to Scraper"):
st.session_state["setup_tab"] = False
st.session_state["scraper"] = True
#setting up parameters from widgets for scraper tab
st.rerun()
In the above code, st.rerun()
is used to refresh the app and trigger the conditional logic in the main function to move to the scraper stage.
Scraper Tab
The scraper_tab
function processes and displays the job listings.
class JobScraperApp:
def __init__(self, data):
#getting required parameters from st.session_state
def show_jobs(self):
if self.current_job_index < len(self.filtered_df):
#job scraping widgets
if st.sidebar.button("Reject"):
self.current_job_index += 1
st.session_state["current_job_index"] = self.current_job_index
st.rerun()
for resume in self.resumes:
if st.sidebar.button(resume):
self.current_job_index += 1
st.session_state["current_job_index"] = self.current_job_index
job["resume_type"] = resume
self.selected_jobs.append(job)
st.session_state["selected_jobs"] = self.selected_jobs
st.rerun()
else:
st.session_state["scraper_tab"] = False
st.session_state["result_tab"] = True
st.rerun()
In the show_jobs
method, st.rerun()
is used to refresh the app after each user action, such as rejecting a job or selecting a resume. This ensures that the job list is updated and the current job index is incremented correctly. When all jobs are processed, st.rerun()
is called to transition to the result tab.
Conclusion
Handling page transitions in Streamlit using session state and st.rerun()
provides a straightforward way to build interactive applications with multiple stages. This method ensures that the application remains responsive and user-friendly, offering a seamless experience for the users.
Through this approach, I was able to create a dynamic application that efficiently handles user inputs, processes data, and presents results in a user-friendly manner.
Feel free to check out the code for this application on GitHub to explore its implementation further.