✨ Announcing our seed funding led by Lux Capital! Read more about it on our blog
DocsBlogChangelog

Search documentation...

/

Star

12k+

[ Learn ]

[ Concepts ]

[ Reference ]

Vars


Vars are any fields in your app that may change over time.

Base Vars


Base vars are defined as fields in your State class.
They can have a set default value. If you don't provide a default value, you must provide a type annotation.
AAPL
$150
increased by4%
class TickerState(rx.State):
    ticker: str = "AAPL"
    price: str = "$150"


def index():
    return rx.stat_group(
        rx.stat(
            rx.stat_label(TickerState.ticker),
            rx.stat_number(TickerState.price),
            rx.stat_help_text(
                rx.stat_arrow(type_="increase"),
                "4%",
            ),
        ),
    )
In this example, ticker and price are base vars in the app, which can be modified at runtime.

Computed Vars


Computed vars are vars that are computed from other properties. They are defined as methods in your State class with the @rx.var decorator.
Try typing in the input box and clicking out.

HELLO

class UppercaseState(rx.State):
    text: str = "hello"

    @rx.var
    def upper_text(self) -> str:
        # This will be recomputed whenever `text` changes.
        return self.text.upper()

    def index():
        return rx.vstack(
            rx.heading(UppercaseState.upper_text),
            rx.input(
                on_blur=UppercaseState.set_text,
                placeholder="Type here...",
            ),
        )
Here, upper_text is a computed var that always holds the upper case version of text.
We recommend always using type annotations for computed vars.

Var Operations


Within your frontend components, you cannot use arbitrary Python functions on the state vars. For example, the following code will not work.
class State(rx.State):
    number: int


def index():
    # This will be compiled before runtime, when we don't know the value of `State.number`.
    # Since `float` is not a valid var operation, this will throw an error.
    rx.text(float(State.number))
This is because we compile the frontend to Javascript, but the value of State.number is only known at runtime. You can use computed vars for more complex operations.
However, you can perform basic operations with vars within components, as seen below.

I just bought a bunch of DOGE

coins = ["BTC", "ETH", "LTC", "DOGE"]


class VarSelectState(rx.State):
    selected: str = "DOGE"


def index():
    return rx.vstack(
        # Using a var operation to concatenate a string with a var.
        rx.heading(
            "I just bought a bunch of "
            + VarSelectState.selected
        ),
        rx.select(
            coins,
            value=VarSelectState.selected,
            on_change=VarSelectState.set_selected,
        ),
    )
You can also combine multiple var operations together, as seen in the next example.

The number is 0

Even

import random


class VarNumberState(rx.State):
    number: int

    def update(self):
        self.number = random.randint(0, 100)


def index():
    return rx.vstack(
        rx.heading(
            f"The number is {VarNumberState.number}"
        ),
        # Var operations can be composed for more complex expressions.
        rx.cond(
            VarNumberState.number % 2 == 0,
            rx.text("Even", color="green"),
            rx.text("Odd", color="red"),
        ),
        rx.button("Update", on_click=VarNumberState.update),
    )
Here, we could have made a computed var that returns the parity of number, but it can be simpler just to use a var operation instead.

Backend Vars


Backend vars are only stored on the backend and are not sent to the client. They have the advantage that they don't need to be JSON serializable. This means you can only use them within event handlers, they can't be used in frontend components.
Backend vars are prefixed with an underscore.

Sum: 6

import numpy as np


class BackendState(rx.State):
    text: str = "Hello World"
    _backend: np.ndarray = np.array([1, 2, 3])

    @rx.var
    def sum(self) -> int:
        return int(self._backend.sum())

    def click(self):
        # Add the next number to the array.
        self._backend = np.append(
            self._backend, [len(self._backend)]
        )


def index():
    return rx.vstack(
        rx.text(f"Sum: {BackendState.sum}"),
        rx.button("Click Me", on_click=BackendState.click),
    )

Client-side Storage


You can use the browser's local storage to persist state between sessions. This allows user preferences, authentication cookies, other bits of information to be stored on the client and accessed from different browser tabs.
A client-side storage var looks and acts like a normal str var, except it is annotated with either rx.Cookie or rx.LocalStorage depending on where the value should be stored. By default, the key name will be the same as the var name, but this can be overridden.
Try entering some values in the text boxes below and then load the page in a separate tab or check the storage section of browser devtools to see the values saved in the browser.

my_cookie

my_local_storage

custom_cookie

class ClientStorageState(rx.State):
    my_cookie: rx.Cookie = ""
    my_local_storage: rx.LocalStorage = ""
    custom_cookie: rx.Cookie = rx.Cookie(
        name="CustomNamedCookie", max_age=3600
    )


def index():
    return rx.vstack(
        rx.hstack(
            rx.text("my_cookie"),
            rx.input(
                value=ClientStorageState.my_cookie,
                on_change=ClientStorageState.set_my_cookie,
            ),
        ),
        rx.hstack(
            rx.text("my_local_storage"),
            rx.input(
                value=ClientStorageState.my_local_storage,
                on_change=ClientStorageState.set_my_local_storage,
            ),
        ),
        rx.hstack(
            rx.text("custom_cookie"),
            rx.input(
                value=ClientStorageState.custom_cookie,
                on_change=ClientStorageState.set_custom_cookie,
            ),
        ),
    )
← State OverviewEvents →

Copyright © 2023 Pynecone, Inc.