Skip to content

Feature/st.rerun #816

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Sep 19, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ st.header(st.session_state['name'])

#### Logic nested in a button with a rerun

Although callbacks are often preferred to avoid extra reruns, our first 'John Doe'/'Jane Doe' example can be modified by adding [`st.experimental_rerun`](/library/api-reference/control-flow/st.experimental_rerun) instead. If you need to acces data in `st.session_state` before the button that modifies it, you can include `st.experimental_rerun` to rerun the script after the change has been committed. This means the script will rerun twice when a button is clicked.
Although callbacks are often preferred to avoid extra reruns, our first 'John Doe'/'Jane Doe' example can be modified by adding [`st.rerun`](/library/api-reference/control-flow/st.rerun) instead. If you need to acces data in `st.session_state` before the button that modifies it, you can include `st.rerun` to rerun the script after the change has been committed. This means the script will rerun twice when a button is clicked.

```python
import streamlit as st
Expand All @@ -220,11 +220,11 @@ st.header(st.session_state['name'])

if st.button('Jane'):
st.session_state['name'] = 'Jane Doe'
st.experimental_rerun()
st.rerun()

if st.button('John'):
st.session_state['name'] = 'John Doe'
st.experimental_rerun()
st.rerun()

st.header(st.session_state['name'])
```
Expand All @@ -247,7 +247,7 @@ st.text_input('Name', key='name')
if st.button('Clear name'):
st.session_state.name = ''
if st.button('Streamlit!'):
set_name('Streamlit')
st.session_state.name = ('Streamlit')
```

</Important>
Expand Down
16 changes: 8 additions & 8 deletions content/library/advanced-features/forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ The purpose of a form is to override the default behavior of Streamlit which rer

1. The user changes a widget's value on the frontend.
2. The widget's value in `st.session_state` and in the Python backend (server) is updated.
3. The script rerun begins.
3. The script rerun begins.
4. If the widget has a callback, it is executed as a prefix to the page rerun.
5. When the updated widget's function is executed during the rerun, it outputs the new value.

Expand Down Expand Up @@ -188,7 +188,7 @@ with st.form('addition'):

<Cloud src="https://doc-forms-process2.streamlit.app/?embed=true" height="400"/>

### Use `st.experimental_rerun`
### Use `st.rerun`

If your process affects content above your form, another alternative is using an extra rerun. This can be less resource-efficient though, and may be less desirable that the above options.

Expand All @@ -213,15 +213,15 @@ with st.form('addition'):
# a second rerun when the form is submitted to update the value above.
st.session_state.sum = a + b
if submit:
st.experimental_rerun()
st.rerun()
```

<Cloud src="https://doc-forms-process3.streamlit.app/?embed=true" height="400"/>

## Limitations

* Every form must contain a `st.form_submit_button`.
* `st.button` and `st.download_button` cannot be added to a form.
* `st.form` cannot be embedded inside another `st.form`.
* Callback functions can only be assigned to `st.form_submit_button` within a form; no other widgets in a form can have a callback.
* Interdependent widgets within a form are unlikely to be particularly useful. If you pass `widget1`'s value into `widget2` when they are both inside a form, then `widget2` will only update when the form is submitted.
- Every form must contain a `st.form_submit_button`.
- `st.button` and `st.download_button` cannot be added to a form.
- `st.form` cannot be embedded inside another `st.form`.
- Callback functions can only be assigned to `st.form_submit_button` within a form; no other widgets in a form can have a callback.
- Interdependent widgets within a form are unlikely to be particularly useful. If you pass `widget1`'s value into `widget2` when they are both inside a form, then `widget2` will only update when the form is submitted.
2 changes: 1 addition & 1 deletion content/library/api-cheat-sheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ st.video(data)
# Stop execution immediately:
st.stop()
# Rerun script immediately:
st.experimental_rerun()
st.rerun()

# Group multiple widgets:
>>> with st.form(key='my_form'):
Expand Down
4 changes: 2 additions & 2 deletions content/library/api/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1699,14 +1699,14 @@ st.stop()
```

</RefCard>
<RefCard href="/library/api-reference/control-flow/st.experimental_rerun">
<RefCard href="/library/api-reference/control-flow/st.rerun">

#### Rerun script

Rerun the script immediately.

```python
st.experimental_rerun()
st.rerun()
```

</RefCard>
Expand Down
4 changes: 2 additions & 2 deletions content/library/api/control-flow/control-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ st.stop()

</RefCard>

<RefCard href="/library/api-reference/control-flow/st.experimental_rerun">
<RefCard href="/library/api-reference/control-flow/st.rerun">

#### Rerun script

Rerun the script immediately.

```python
st.experimental_rerun()
st.rerun()
```

</RefCard>
Expand Down
8 changes: 1 addition & 7 deletions content/library/api/control-flow/experimental_rerun.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,4 @@ slug: /library/api-reference/control-flow/st.experimental_rerun
description: st.experimental_rerun will rerun the script immediately.
---

<Important>

This is an experimental feature. Experimental features and their APIs may change or be removed at any time. To learn more, click [here](/library/advanced-features/prerelease#experimental-features).

</Important>

<Autofunction function="streamlit.experimental_rerun" />
<Autofunction function="streamlit.experimental_rerun" deprecated={true} deprecatedText="<code>st.experimental_rerun</code> was deprecated in version 1.27.0. Use <a href='/library/api-reference/control-flow/st.rerun'><code>st.rerun</code></a> instead."/>
59 changes: 59 additions & 0 deletions content/library/api/control-flow/rerun.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: st.rerun
slug: /library/api-reference/control-flow/st.rerun
description: st.rerun will rerun the script immediately.
---

<Autofunction function="streamlit.rerun" />

### Caveats for `st.rerun`

`st.rerun` is one of the tools to control the logic of your app. While it is great for prototyping, there can be adverse side effects:

- Additional script runs may be inefficient and slower.
- Excessive reruns may complicate your app's logic and be harder to follow.
- If misused, infinite looping may crash your app.

In many cases where `st.rerun` works, [callbacks](/library/api-reference/session-state#use-callbacks-to-update-session-state) may be a cleaner alternative. [Containers](/library/api-reference/layout) may also be helpful.

### A simple example in three variations

###### Using `st.rerun` to update an earlier header

```python
import streamlit as st

if "value" not in st.session_state:
st.session_state.value = "Title"

##### Option using st.rerun #####
st.header(st.session_state.value)

if st.button("Foo"):
st.session_state.value = "Foo"
st.rerun()
```

###### Using a callback to update an earlier header

```python
##### Option using a callback #####
st.header(st.session_state.value)

def update_value():
st.session_state.value = "Bar"

st.button("Bar", on_click=update_value)
```

###### Using containers to update an earlier header

```python
##### Option using a container #####
container = st.container()

if st.button("Baz"):
st.session_state.value = "Baz"

container.header(st.session_state.value)
```
4 changes: 4 additions & 0 deletions content/menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,13 @@ site_menu:
- category: Streamlit library / API reference / Control flow / st.form_submit_button
url: /library/api-reference/control-flow/st.form_submit_button
isVersioned: true
- category: Streamlit library / API reference / Control flow / st.rerun
url: /library/api-reference/control-flow/st.rerun
isVersioned: true
- category: Streamlit library / API reference / Control flow / st.experimental_rerun
url: /library/api-reference/control-flow/st.experimental_rerun
isVersioned: true
isDeprecated: true
- category: Streamlit library / API reference / Utilities
url: /library/api-reference/utilities
- category: Streamlit library / API reference / Utilities / st.set_page_config
Expand Down
2 changes: 1 addition & 1 deletion python/api-examples-source/forms.form_process3.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@
# a second rerun when the form is submitted to update the value above.
st.session_state.sum = a + b
if submit:
st.experimental_rerun()
st.rerun()
Loading