# how to work with mutable data and reactive vars
import solara
import pandas
import dataclasses
store = {
'books':'3',
'shelves':'2',
'racks':'1'
} # inventory
@dataclasses.dataclass
class VersionedMutableData:
data: dict
version: int
# wrap mutable state in a versioned object
rstore = solara.reactive(VersionedMutableData(data=store, version=0))
# convenience for setting a new store value
def set_store(store: dict):
new_version = rstore.peek().version + 1
rstore.value = VersionedMutableData(data=store, version=new_version)
@solara.component
def MarkdownEditor(field: str):
store = rstore.value.data
value = store[field]
def store_updater(newval):
store[field] = newval # we mutate, which is generally not recommended
set_store(store) # but this one puts a new object (with a version) around it
print('updated', store) # debug
solara.InputText('value '+field, value=value, on_value=store_updater)
solara.Markdown(value)
@solara.component
def OtherDisplay1(store: dict):
solara.Text(f"I do not update when store is mutated: {store}")
@solara.component
def OtherDisplay2(store: VersionedMutableData):
solara.Text(f"I do update when store is mutated: {store.data}")
@solara.component
def Page():
store = rstore.value.data
for fld in store.keys():
MarkdownEditor(fld)
print('showing as frame', store)
df = pandas.DataFrame([[k,v] for k,v in store.items()], columns=['item','value'])
solara.DataFrame(df)
# possible danger is passing the mutated object as argument to component who
# also do not see a change
OtherDisplay1(rstore.value.data)
# passing the verioned object will work
OtherDisplay2(rstore.value)