# Source: https://dev.writer.com/framework/application-state.md

# Application state

Each session is assigned a unique application state by the Framework.

## Initializing state

To set the initial application state, use the `wf.init_state()` method with a dictionary argument.

<Tip>
  All user sessions will start with a clone of this initial state.
</Tip>

```py  theme={null}
import writer as wf

# Define the initial state
initial_state = wf.init_state({
    "counter": 0,
})

# Define an event handler that modifies the state
# It receives the session state as an argument and mutates it
def increment(state):
    state["counter"] += 1
```

In the above example, each session begins with a `counter` at 0. As users interact with the application and activate event handlers, their session's `counter` value will change. For instance, if a user triggers the `increment` handler three times, their counter will increase to 3.

To access the `counter` value in the Builder, use @{counter}.

### Managing nested state elements

To include nested elements in your state, use nested dictionaries:

```python  theme={null}
# Example of nested state initialization
wf.init_state({
    "counter": 0,
    "my_app": {
        "title": "Nested value"
    }
})
```

You can reference nested elements in the Builder as `@{my_app.title}`.

### Backend-only state elements

By default, all of the elements in the session state are sent to the front-end.

<Warning>
  All state elements are transmitted to the front-end by default, regardless of their visibility in the user interface.
</Warning>

To keep certain state elements private (back-end-only), prefix them with an underscore `_`. This is useful in several scenarios:

1. When data synchronization to the front-end is unnecessary.
2. When data cannot be serialized for the front-end, such as database connections.
3. When data is sensitive to the specific session and should remain confidential.

These elements remain in the back-end and cannot be accessed from the Builder.

## Managing files and binary data

In components where the Builder interfaces with external data, such as images, it often requires the use of data URLs. The source for an *Image* component, for example, can be a standard URL or a data URL.

Packing Files and Binary Data: Files and binary data can be converted to data URLs before they are sent to the front-end. Use `wf.pack_file()` and `wf.pack_bytes()` for this purpose. The `mime_type` argument, while optional, specifies the media type, helping the browser to correctly handle the data.

```python  theme={null}
import writer as wf

# Initialize state with various data types
wf.init_state({
    # Reference a file by its filesystem path
    "sales_spreadsheet": wf.pack_file("sales_spreadsheet.xlsx"),

    # Use a file-like object that implements a .read() method
    "main_image": wf.pack_file(image_file, mime_type="image/jpeg"),

    # Convert raw bytes specifying a MIME type
    "my_bytes": wf.pack_bytes(b"\x31\x33\x33\x37", mime_type="text/plain"),

    # Directly assign raw bytes without a MIME type
    "my_raw_bytes": b"\x31\x33\x33\x37",
})
```

## Handling non-standard data types

The front-end cannot directly display complex data types such as Pandas dataframes or Matplotlib figures. Such objects must be serialized before being sent.

<Tabs>
  <Tab title="Matplotlib figures">
    Matplotlib figures are converted to PNG data URLs, which can be shown using a standard *Image* component.

    ```python  theme={null}
    wf.init_state({
        "my_matplotlib_fig": fig,
    })
    ```

    The element can be used in an *Image* component in the Builder by setting the source to `@{my_matplotlib_fig}`. Alternatively, as data inside a *File Download* component.
  </Tab>

  <Tab title="Plotly graphs">
    Plotly graphs are converted to Plotly JS specifications, using JSON. They can be used in *Plotly Graph* components.
  </Tab>

  <Tab title="Altair charts">
    Altair charts are converted to Vega Lite specifications, based on JSON. They can be used in *Vega Lite Chart* components.
  </Tab>

  <Tab title="Pandas dataframes">
    Pandas dataframes are converted to JSON and can be used in *Dataframe* components.
  </Tab>
</Tabs>

## State schema

State schema is a feature that allows you to define the structure of the state.
This is useful for ensuring that the state is always in the expected format.

Schema allows you to use features like

* typing checking with mypy / ruff
* autocomplete in IDEs
* declare dictionaries
* automatically calculate mutations on properties

more into [Advanced > State schema](./state-schema)

```python  theme={null}
import writer as wf

class AppSchema(wf.WriterState):
    counter: int

initial_state = wf.init_state({
    "counter": 0
}, schema=AppSchema)

# Event handler
# It receives the session state as an argument and mutates it
def increment(state: AppSchema):
    state.counter += 1
```