State beetwen pages

hi all.


Im trying to acces the var dasboarditems from a diferente pages where its call the event but i doest work

Page dashboard
I have a dashboard with orders and in this page i call the event sendOrdersToWaitingList in my dashboardState. This work, i get the state from WaitingListState run an operation a get the numbes that i need, also print in console.

Bue when im trying to access the Waitinglist state from another page the var is empy.

I dont understand how to do it. Every time an order is created its need to appear in the other page.

Thanks

@fafunas what you have should work - I have the following example that works on my end:

import json

import reflex as rx


class State(rx.State):
    value: list = []

    async def foo(self, item):
        self.value.append(item)
        print(json.dumps(self.value))


class State2(rx.State):
    value: list[int]

    async def run_foo(self):
        state = await self.get_state(State)
        await state.foo(42)


def index() -> rx.Component:
    return rx.button("Foo", on_click=State2.run_foo)


app = rx.App()
app.add_page(index)

Could you past a minimal code sample that doesn’t work - we can take a further look.

Hi, thanks for the reply. After reading the documentation, I think I’ve figured it out. The code is working like this. The issue is that I have two pages with two states, and one page is open in another tab, so I lose the instance.
I need to have one page open in another tab because I display it on another monitor. It’s like a food truck system: when your order is ready or in preparation, you can see the status. On one page, I have the dashboard for user input, and on another, just the grid with the orders that should update automatically. I guess I need to implement LocalStorage to share the data between tabs.

You can use rx.LocalStorage(sync=True) and it will automatically push updates to other tabs in the browser when that variable changes. Because different tabs have different state and you might not want everything in local storage, you can use some unique identifier and look up the state/data from the database when needed.

Thanks, I managed to use the data in LocalStorage and its work well. I also manage to put the data in my component, but when the data changes in the LS, my component doesn´t render again

This is my dashboard State

import reflex as rx
from ..services.shiftServices import startShiftServices, endShiftServices,checkOpenShiftStatusService, getUnfinishdOrders
from ..services.productServices import getAllProductsServices
from ..services.orderServices import cleanData, createOrderServices,getAllOrdersServices, updateFinishtime, getDataCard
from ..services.waitinglistservices import getNumOrdersServices
from ..models.product_model import Products
from ..models.dashboardModel import OrderType
import json


class DashboardState(rx.State):
    shift_status:bool 
    products: list[Products] = []
    orderTable: list[OrderType] = []
    order_data: dict = {}
    openedDialog: bool = False
    productconfirm: list[dict]=[]
    statusCards: dict={}
    lsprep: str=rx.LocalStorage("{}",sync=True)
    lsret: str=rx.LocalStorage("{}",sync=True)
    
    def closeDialog(self):
        self.openedDialog=False
    
        
    def handle_submit(self,data={}):
        items=cleanData(data)
        self.productconfirm = items.productos
        self.order_data=items
        self.openedDialog = True
        
    def waitingOrders(self):
        ordenes= getNumOrdersServices(self.orderTable)
        self.lsprep= json.dumps(ordenes[0])
        self.lsret= json.dumps(ordenes[1])
        
         
    @rx.event(background=True)
    async def createOrder(self):
        async with self:
            createOrderServices(self.order_data)
            self.openedDialog = False
            self.orderTable= await getAllOrdersServices()
            self.statusCards = getDataCard()
            self.waitingOrders()

My other Waiting State for the other page

import reflex as rx
from ..states.dashboardState import DashboardState
import json

class WaitState(rx.State):
    prep:list=[]
    ready:list=[]
    
    
    async def getLsdata(self):
        state= await self.get_state(DashboardState)
        self.prep= self.get_value(json.loads(state.lsprep))
        self.ready= self.get_value(json.loads(state.lsret))
        print(self.prep)
        print(self.ready)
     
    
    async def onload(self):
        await self.getLsdata()

And the component of my page

import reflex as rx
from ..styles.styles import Size
from ..states.waintingState import WaitState

def waiting() -> rx.Component:
    return rx.vstack(
        rx.heading(
            "Listado de Ordenes",
            font_size=Size.VERY_BIG,
            text_align="center",
            width="100%",
            margin=Size.MEDIUM
        ),
        rx.button("Prueba",
                  on_click=WaitState.onload),
        rx.grid(
            rx.vstack(
                rx.heading("En Preparacion",
                           text_align="center",
                           font_size=Size.BIG,
                           width="100%",
                           margin="20px 0px",
                           border_bottom="2px solid black"),
                rx.box(
                  rx.cond(
                      WaitState.prep,
                      rx.foreach(
                          WaitState.prep,orderitem
                      )
                  )
                ),
                width="100%",
                height="100vh"
            ),
            rx.vstack(
                rx.heading("Para Retirar",
                           text_align="center",
                           font_size=Size.BIG,
                           width="100%",
                           margin="20px 0px",
                           border_bottom="2px solid black"),
                rx.box(
                  rx.cond(
                      WaitState.ready,
                      rx.foreach(
                          WaitState.ready,orderitem
                      )
                  )
                ),
                width="100%",
                height="100vh"
            ),
            columns="2",
            #spacing="9",
            width="100%"
        )
    )
    
def orderitem(x: rx.Var[int])->rx.Component:
    return rx.text(x)

I need that this component change everytime the LS changes.

thanks

[mod edit: formatting]

The local state is synced, but the WaitState prep and ready vars are not linked to them directly and only are updated when the button is pressed. If you want them to react to the local storage changes, have WaitState inherit from DashboardState and make prep and ready into cached computed vars.

class WaitState(DashboardState):    
    @rx.var(cache=True)
    def prep(self) -> dict:
        return json.loads(state.lsprep)

    @rx.var(cache=True)
    def ready(self) -> dict:
        return json.loads(state.lsret)

The typing might be wrong here, not clear from your code if these are supposed to be list or dict because the default localstorage value is “{}”, but the annotation for the previous state vars was list, so please adjust accordingly.

The important part is that by making these computed vars, whenever the localstorage value changes, they will reactively update, and in turn update your UI.

Thanks, that work great. Just what I need.

1 Like