Function in Button doesn't keep value

Summary

I’ve created a Python function to add data to JSON from inputs. I’ve try to associate the function to a button but when I press the button for the second time to add data it just add the last data set to the JSON.

Steps to reproduce

Code snippet:
Python function

import json
def add_data_json(data, subassembly, shape, link, material):
    new_data = {
        "Enabled": True,
        "SubassemblyName": subassembly,
        "ShapeCodes": shape.split(","),
        "LinkCodes": link.split(","),
        "Category": "Generic",
        "Material": material
    }
    data["CorridorMappingRules"].append(new_data)
    return json.dumps(data)

def generate_json(data, filename):
    with open(filename, 'w') as file:
        json.dump(data, file, indent=4)

Streamlit page

import streamlit as st
import functions as fu

st.title('JSON Materiales IW')
st.write('''
Esta webapp permite generar JSON para asignar materiales en IW.
''')

subassembly_name = st.text_input("Nombre del subassembly:")
shape_name = st.text_input("Nombre del shape:")
link_name = st.text_input("Nombre del link:")
material_name = st.selectbox(
        'Nombre del material:',('Material/Land Cover/Riverstone','Material/Land Cover/Gravel - Mixed',
        'Material/Land Cover/Gravel - Med Grey','Material/Land Cover/Gravel - Grey Planting',
        'Material/Colors/Black','Material/Land Cover/Sand - Planting Sand',
        'Material/Land Cover/Sand - Dark Brown','Material/Colors/Transparent',
        'Material/Land Cover/Gravel - Small Grey','Material/Land Cover/Border Stone',
        'Material/Land Cover/Brown Square Tile','Material/Land Cover/Square Stone w_Grass')
)

data = {"Version": "0.0.1",
        "CorridorMappingRules": [],
        "TopSegments": "top",
	    "DatumSegments": "datum"
        }

if st.button('Añadir'):
    js = fu.add_data_json(data, subassembly_name, shape_name, link_name, material_name)
    st.write(js)

if st.button('Generar'):
    fu.generate_json(data, "materiales.json")
    st.write('Se generó el JSON.')

Expected behavior:

I would like the button “Añadir” to add data multiple times.

Actual behavior:

When I press the button it just adds the last set of data, deleting the previous.

Debug info

  • Streamlit version: 1.19.0
  • Python version: 3.11.2
  • Didn’t use Conda or virtual envs.
  • OS version: Windows 11
  • Browser version: Slimjet (based on Chromium)

Requirements file

No requeriments. JSON library comes with Python.

Additional information

Also, if it’s not too much to ask I would like guide on how to export to JSON. When I het the button “Generar” associated to the function generate_json it doesn’t generate a JSON with the data, just the initial JSON. Thank you so much. I’m just starting to learn Slimjet and using Python for something real.

If you want to accumulate changes in an object, you will need to read and write to it in session state.

Simple example:

import streamlit as st

if 'response' not in st.session_state:
    st.session_state.response = 'Meow'

def feed_me():
    st.session_state.response += ' meow'

st.button('What does kitty want?', on_click=feed_me)

st.write(st.session_state.response)

And as for buttons, they are true only on the page load right after their click and then go back to false. So if you want to show (and keep showing) something after a button click, you won’t want to tie it directly to the button.

Actually I just wrote a blog post on this if you want to check out the first two section here: 10 most common explanations on the Streamlit forum