@@ -52,6 +52,8 @@ def main():
52
52
53
53
# Render the image bytes in the UI:
54
54
hd.image(get_chart_image(fig), width=20)
55
+
56
+ hd.run(main)
55
57
```
56
58
57
59
Note that `matplotlib.use("Agg")` is important. It tells
@@ -64,115 +66,128 @@ def main():
64
66
"""
65
67
)
66
68
67
- p .heading ("## Asynchronous Chart Creation with `task` " )
69
+ p .heading ("## Responding to Theme Mode " )
68
70
69
71
docs_markdown (
70
72
"""
71
73
72
- In the example above, The chart is re-created on every run
73
- of the app function. We can use a @component(task) to
74
- create the chart only once and cache its result:
74
+ By default, Matplotlib chart images are rendered on white
75
+ background. There's currently no easy way to match the
76
+ chart's color scheme to Hyperdiv's theme exactly, but
77
+ Matplotlib provides a basic way to render a chart in dark
78
+ or light mode. We can then sync the chart's theme mode to
79
+ Hyperdiv's theme mode.
75
80
76
81
```py-nodemo
77
- def get_chart():
78
- fig, ax = plt.subplots()
79
- ax.plot([1, 2, 3, 4], [10, 11, 12, 13])
82
+ def main():
83
+ theme = hd.theme()
80
84
81
- return get_chart_image(fig )
85
+ line_data = ([1, 2, 3, 4], [10, 11, 12, 13] )
82
86
83
- def main():
84
- task = hd.task()
85
- task.run(get_chart)
86
- if task.result:
87
- hd.image(task.result, width=20)
88
- ```
87
+ if theme.is_dark:
88
+ # Render the matplotlib chart in dark mode:
89
+ with plt.style.context("dark_background"):
90
+ fig, ax = plt.subplots()
91
+ ax.plot(*line_data)
92
+ else:
93
+ # Render it in light mode:
94
+ fig, ax = plt.subplots()
95
+ ax.plot(*line_data)
89
96
90
- In this example, the function `get_chart` is called only
91
- once and the image bytes are cached in `task.result`.
97
+ # Render the image bytes in the UI:
98
+ hd.image(get_chart_image(fig), width=20)
99
+ ```
92
100
93
101
"""
94
102
)
95
103
96
- p .heading ("## Dynamically Updating Charts " )
104
+ p .heading ("## Caching Chart Components with `@cached` " )
97
105
98
106
docs_markdown (
99
107
"""
100
108
101
- We can also re-create a chart on demand, with new data.
109
+ Using the pattern above, the chart will be re-created on
110
+ every unrelated run of the app function. We can use the
111
+ @component(cached) decorator to avoid re-creating the
112
+ chart on every run.
102
113
103
114
```py-nodemo
104
- def get_chart(data):
105
- fig, ax = plt.subplots()
106
- ax.plot(*data )
115
+ @hd.cached
116
+ def chart():
117
+ theme = hd.theme( )
107
118
108
- return get_chart_image(fig )
119
+ line_data = ([1, 2, 3, 4], [10, 11, 12, 13] )
109
120
110
- def main():
111
- state = hd.state(
112
- chart_data=([1, 2, 3, 4], [10, 11, 12, 13])
113
- )
121
+ if theme.is_dark:
122
+ with plt.style.context("dark_background"):
123
+ fig, ax = plt.subplots()
124
+ ax.plot(*line_data)
125
+ else:
126
+ fig, ax = plt.subplots()
127
+ ax.plot(*line_data)
114
128
115
- task = hd.task()
116
- task.run(get_chart, state.chart_data)
117
- if task.result:
118
- hd.image(task.result, width=20)
129
+ hd.image(get_chart_image(fig), width=20)
119
130
120
- if hd.button("Update Chart").clicked:
121
- state.chart_data = ([1, 2, 3, 4], [5, 20, 8, 10])
122
- task.clear()
131
+ def main():
132
+ chart()
133
+
134
+ state = hd.state(count=0)
135
+ if hd.button("Click Me").clicked:
136
+ state.count += 1
137
+ hd.text(state.count)
123
138
```
124
139
125
- In this example, we store the chart's line data in
126
- @component(state). When the `Update Chart` button is
127
- clicked, we update the chart data and clear the task. The
128
- task will then re-run with the new chart data, and an
129
- updated chart will be rendered.
140
+ In this example, when the app first loads, `chart()` is
141
+ called and its resulting virtual DOM is cached.
142
+
143
+ For demonstration, there's an unrelated click counter on
144
+ the page. When we click the `Click Me` button, the app
145
+ re-runs but the call to `chart()` does not re-run the
146
+ `chart` function, and instead uses its cached virtual DOM.
147
+
148
+ Also, when the theme mode is switched between light and
149
+ dark, the `chart` function's dependency on theme mode will
150
+ be invalidated and the function will re-run, rendering the
151
+ chart in the new theme mode.
130
152
131
153
"""
132
154
)
133
155
134
- p .heading ("## Responding to Theme Mode " )
156
+ p .heading ("## Dynamically Updating Charts " )
135
157
136
158
docs_markdown (
137
159
"""
138
160
139
- By default, Matplotlib chart images are rendered on white
140
- background. There's currently no easy way to match the
141
- chart's color scheme to Hyperdiv's theme exactly, but
142
- Matplotlib provides a basic way to render a chart in dark
143
- or light mode. We can then sync the chart's theme mode to
144
- Hyperdiv's theme mode.
161
+ We can re-create the chart on demand, with new data:
145
162
146
163
```py-nodemo
147
- def get_chart(data, is_dark):
148
- if is_dark:
164
+ @hd.cached
165
+ def chart(state):
166
+ theme = hd.theme()
167
+
168
+ if theme.is_dark:
149
169
with plt.style.context("dark_background"):
150
170
fig, ax = plt.subplots()
151
- ax.plot(*data )
171
+ ax.plot(*state.line_data )
152
172
else:
153
173
fig, ax = plt.subplots()
154
- ax.plot(*data )
174
+ ax.plot(*state.line_data )
155
175
156
- return get_chart_image(fig)
176
+ hd.image( get_chart_image(fig), width=20 )
157
177
158
178
def main():
159
- theme = hd.theme()
160
- task = hd.task()
161
- task.run(
162
- get_chart,
163
- ([1, 2, 3, 4], [5, 20, 8, 10]),
164
- # Pass the current theme mode to the task:
165
- theme.is_dark
179
+ state = hd.state(
180
+ line_data=([1, 2, 3, 4], [10, 11, 12, 13])
166
181
)
167
182
168
- if task.result:
169
- hd.image(task.result, width=20)
183
+ chart(state)
170
184
171
- # When the Hyperdiv theme changes, re-render the chart
172
- # in the new theme mode:
173
- if theme.changed:
174
- task.clear()
185
+ if hd.button("Update Chart").clicked:
186
+ state.line_data = ([1, 2, 3, 4], [5, 20, 8, 10])
175
187
```
176
188
189
+ In this example, we store the chart's line data in
190
+ @component(state). When the `Update Chart` button is
191
+ clicked, an updated chart will be rendered.
177
192
"""
178
193
)
0 commit comments