Skip to content

Commit

Permalink
docs: Updating examples
Browse files Browse the repository at this point in the history
- Adding some more basic examples, adding only one concept with each example
  - Start with a couple one-liners
- Clean up state, need to start cleaning up after "Using State"
  • Loading branch information
mofojed committed Mar 20, 2024
1 parent 19582de commit 7fc0f70
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 16 deletions.
91 changes: 75 additions & 16 deletions plugins/ui/examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,94 @@ docker run --rm --name deephaven-ui -p 10000:10000 --pull=always ghcr.io/deephav
You'll need to find the link to open the UI in the Docker logs:
![docker](assets/docker.png)

# Basic `use_state` Examples
# Components

deephaven.ui uses functional components with "hooks" to create components. The most useful and basic hook is the `use_state` hook, which allows you to create a stateful component. The `use_state` hook returns a tuple of the current value of the state and a function to update the state. The function returned by `use_state` can be called with a new value to update the state, and the component will re-render with the new value. People familiar with React will be familiar with this paradigm.
Get started by importing the `deephaven.ui` package as `ui`:

The below examples show a simple usage of the `use_state` hook, building some of the basic examples on the [React useState docs](https://react.dev/reference/react/useState#examples-basic).
```python
from deephaven import ui
```

The `ui` package contains many _components_, which you can display in the UI:

```python
hello_world = ui.heading("Hello World!")
```

![Basic Hello World example](assets/hello_world.png)

## Counter (number)
By assigning the component to the `hello_world` variable, it was displayed in the UI in a panel named `hello_world`.

A simple example to demonstrate how state can be used using the `use_state` hook. `count` holds the value of the counter, and pressing the button increments the number.
## Handling Events

We define our `counter` component as a function using the `@ui.component` decorator. This decorator allows the component to be rendered in the UI, when we assign the result of it to a value with the `c = counter()` line. The `counter` function returns a `ui.action_button` component, which is a [button that can be pressed](https://react-spectrum.adobe.com/react-spectrum/ActionButton.html). The `on_press` argument is a callback that is called when the button is pressed. In this case, we call the `set_count` function returned by `use_state` to update the value of `count`.
Write `lambda` functions to handle events. To write a button that will print event details to the console when clicked:

```python
import deephaven.ui as ui
from deephaven.ui import use_state
my_button = ui.button("Click Me!", on_press=lambda e: print(f"Button was clicked! {e}"))
```

![Whenever the button is pressed, event details are printed to the console.](assets/handling_events.png)

## Creating Custom Components

Use the `@ui.component` decorator to create your own custom components. We can display a heading above a button as our custom custom component:

```python
@ui.component
def counter():
count, set_count = use_state(0)
return ui.action_button(
f"You pressed me {count} times", on_press=lambda _: set_count(count + 1)
)
def ui_foo_bar():
return [
ui.heading("Click button below"),
ui.button("Click Me!", on_press=lambda: print("Button was clicked!")),
]


c = counter()
foo_bar = ui_foo_bar()
```

![Counter](assets/counter.png)
![Custom component being displayed.](assets/foo_bar.png)

## Using State

Often, you'll want to react to the button presses and update the display. For example, to count the number of times a button has been pressed, use `ui.use_state` to introduce a _state variable_ in your custom component:

```python
@ui.component
def ui_counter():
count, set_count = ui.use_state(0)
# ...
```

Returned from `ui.use_state` is a tuple with two values: the current state (`count`), and a function to update that state (`set_count`).

The first time the button is displayed, the count will be `0` because that's the initial value you passed into `ui.use_state`. Call `set_count` when you want to update the state:

```python
@ui.component
def ui_counter():
count, set_count = ui.use_state(0)
return ui.button(f"Pressed {count} times", on_press=lambda: set_count(count + 1))
```

When state is updated, deephaven.ui will call your component again to re-render with the new value. After clicking once it will re-render with `count` set to `1`, then set to `2`, and so on.

Each individual component has it's own state:

```python
@ui.component
def ui_counter():
count, set_count = ui.use_state(0)
return ui.button(f"Pressed {count} times", on_press=lambda: set_count(count + 1))


c1 = ui_counter()
c2 = ui_counter
```

![Each counter has it's own state.](assets/counter.png)

> [!NOTE]
> Functions are prefixed with `use_` are called _hooks_. `use_state` is built-in to deephaven.ui, and there are other hooks built-in shown below. You can also create your own hooks.
> Hooks are special functions. They must only be used at the _top_ of a `@ui.component` or another hook. If you want to use in a conditional or a loop, extract that logic to a new component and put it there.
## Text field (string)

Expand Down Expand Up @@ -190,7 +249,7 @@ import deephaven.ui as ui

@ui.component
def button_event_printer(*children, id="My Button"):
return ui.action_button(
return ui.button(
*children,
on_key_down=print,
on_key_up=print,
Expand Down
Binary file modified plugins/ui/examples/assets/counter.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/ui/examples/assets/foo_bar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/ui/examples/assets/handling_events.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/ui/examples/assets/hello_world.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 7fc0f70

Please sign in to comment.