|
| 1 | +# Hooks |
| 2 | + |
| 3 | +_Hooks_ let you use state and other deephaven.ui features in your components. Hooks are functions that let you "hook into" state and lifecycle features from function components, encapsulating code and logic to avoid duplication. You can either use the built-in hooks or combine them to build your own. |
| 4 | + |
| 5 | +## Example |
| 6 | + |
| 7 | +```python |
| 8 | +from deephaven import ui |
| 9 | + |
| 10 | + |
| 11 | +@ui.component |
| 12 | +def ui_counter(): |
| 13 | + count, set_count = ui.use_state(0) |
| 14 | + return ui.button(f"Pressed {count} times", on_press=lambda: set_count(count + 1)) |
| 15 | + |
| 16 | + |
| 17 | +counter = ui_counter() |
| 18 | +``` |
| 19 | + |
| 20 | +## UI recommendations |
| 21 | + |
| 22 | +1. **Hooks must be used within components or other hooks**: Hooks require a rendering context, and therefore can only be used within component functions or other hooks. They cannot be used in regular Python functions or outside of components. |
| 23 | +2. **All hooks start with `use_`**: For example, `use_state` is a hook that lets you add state to your components. |
| 24 | +3. **Hooks must be called at the _top_ level**: Do not use hooks inside loops, conditions, or nested functions. This ensures that hooks are called in the same order each time a component renders. If you want to use one in a conditional or a loop, extract that logic to a new component and put it there. |
| 25 | + |
| 26 | +## Built-in hooks |
| 27 | + |
| 28 | +Below are all the built-in hooks that deephaven.ui provides. |
| 29 | + |
| 30 | +### State hooks |
| 31 | + |
| 32 | +_State_ lets a component remember some data between renders and trigger a re-render when the data changes. For example, a counter component might use state to keep track of the current count. |
| 33 | + |
| 34 | +The [`use_state`](use_state.md) hook adds state to a component. |
| 35 | + |
| 36 | +### Ref hooks |
| 37 | + |
| 38 | +A _ref_ provides a way to hold a value that isn't used for re-rendering. Unlike with state, updating a ref does not re-render your component. |
| 39 | + |
| 40 | +- [`use_ref`](use_ref.md) returns a mutable ref object whose `.current` property is initialized to the passed argument. |
| 41 | + |
| 42 | +### Effect hooks |
| 43 | + |
| 44 | +An _effect_ hook lets you perform side effects in your components; for example, data fetching, setting up a subscription, and manually synchronizing with an external system. |
| 45 | + |
| 46 | +- [`use_effect`](use_effect.md) lets you perform side effects in your components. |
| 47 | + |
| 48 | +### Performance hooks |
| 49 | + |
| 50 | +_Performance_ hooks let you optimize components for performance. They allow you to memoize expensive computations so that you can avoid re-running them on every render, or skip unnecessary re-rendering. |
| 51 | + |
| 52 | +- [`use_memo`](use_memo.md) lets you memoize expensive computations. |
| 53 | +- [`use_callback`](use_callback.md) lets you cache a function definition before passing to an effect or child component, preventing unnecessary rendering. It's like `use_memo` but specifically for functions. |
| 54 | + |
| 55 | +### Data hooks |
| 56 | + |
| 57 | +_Data_ hooks let you use data from within a Deephaven table in your component. |
| 58 | + |
| 59 | +- [`use_table_data`](use_table_data.md) lets you use the full table contents. |
| 60 | +- [`use_column_data`](use_column_data.md) lets you use the data of one column. |
| 61 | +- [`use_cell_data`](use_cell_data.md) lets you use the data of one cell. |
| 62 | + |
| 63 | +## Create custom hooks |
| 64 | + |
| 65 | +You can create your own hooks to reuse stateful logic between components. A custom hook is a JavaScript function whose name starts with `use` and that may call other hooks. For example, let's say you want to create a custom hook that checks whether a table cell is odd. You can create a custom hook called `use_is_cell_odd`: |
| 66 | + |
| 67 | +```python |
| 68 | +from deephaven import time_table, ui |
| 69 | + |
| 70 | + |
| 71 | +def use_is_cell_odd(table): |
| 72 | + cell_value = ui.use_cell_data(table, 0) |
| 73 | + return cell_value % 2 == 1 |
| 74 | + |
| 75 | + |
| 76 | +@ui.component |
| 77 | +def ui_table_odd_cell(table): |
| 78 | + is_odd = use_is_cell_odd(table) |
| 79 | + return ui.view(f"Is the cell odd? {is_odd}") |
| 80 | + |
| 81 | + |
| 82 | +_table = time_table("PT1s").update("x=i").view("x").tail(1) |
| 83 | +table_odd_cell = ui_table_odd_cell(_table) |
| 84 | +``` |
| 85 | + |
| 86 | +Notice at the end of our custom hook, we check if the cell value is odd and return the result. We then use this custom hook in our component to display whether the cell is odd. |
0 commit comments