|
4 | 4 | "cell_type": "markdown",
|
5 | 5 | "metadata": {},
|
6 | 6 | "source": [
|
7 |
| - "# What is ReactPy?\n", |
| 7 | + "<img src=\"https://raw.githubusercontent.com/reactive-python/reactpy/main/branding/svg/reactpy-logo-landscape.svg\" alt=\"ReactPy Logo\" style=\"min-width: 300px; width: 35%\" />\n", |
8 | 8 | "\n",
|
9 |
| - "ReactPy connects your Python web framework of choice to a ReactJS frontend, allowing you to create **interactive websites without needing JavaScript!**\n", |
| 9 | + "---\n", |
10 | 10 | "\n",
|
11 |
| - "Following ReactJS styling, web elements are combined into [reusable \"components\"](https://reactpy.dev/docs/guides/creating-interfaces/your-first-components/index.html#parametrizing-components). These components can utilize [hooks](https://reactpy.dev/docs/reference/hooks-api.html) and [events](https://reactpy.dev/docs/guides/adding-interactivity/responding-to-events/index.html#async-event-handlers) to create infinitely complex web pages.\n", |
| 11 | + "[ReactPy](https://reactpy.dev/) is a library for building user interfaces in Python without Javascript. ReactPy interfaces are made from components which look and behave similarly to those found in [ReactJS](https://reactjs.org/). Designed with simplicity in mind, ReactPy can be used by those without web development experience while also being powerful enough to grow with your ambitions.\n", |
12 | 12 | "\n",
|
13 |
| - "When needed, ReactPy can [use components directly from NPM](https://reactpy.dev/docs/guides/escape-hatches/javascript-components.html#dynamically-loaded-components). For additional flexibility, components can also be [fully developed in JavaScript](https://reactpy.dev/docs/guides/escape-hatches/javascript-components.html#custom-javascript-components).\n", |
14 | 13 | "\n",
|
15 | 14 | "\n",
|
16 | 15 | "# Getting Started\n",
|
|
60 | 59 | },
|
61 | 60 | "outputs": [],
|
62 | 61 | "source": [
|
63 |
| - "from reactpy import component, html, run\n", |
| 62 | + "from reactpy import component, html\n", |
64 | 63 | "\n",
|
65 | 64 | "\n",
|
66 | 65 | "@component\n",
|
|
186 | 185 | "source": [
|
187 | 186 | "# Using ReactPy With Jupyter Widgets\n",
|
188 | 187 | "\n",
|
189 |
| - "While you can use ReactPy components independently, it may also be useful to integrate them with the rest of the Jupyter Widget ecosystem. Let's consider a ReactPy component that responds to and displays changes from an `ipywidgets.IntSlider`. The ReactPy component will need to accept an `IntSlider` instance as one of its arguments, declare state that will track the slider's value, and register a lister that will update that state via the slider's `IntSlider.observe()` method using an [\"effect\"](https://reactpy.dev/docs/reference/hooks-api.html#use-effect):" |
| 188 | + "It's possible to use Jupyter Widgets in ReactPy components if you convert them first using `reactpy_jupyter.from_widget`." |
| 189 | + ] |
| 190 | + }, |
| 191 | + { |
| 192 | + "cell_type": "code", |
| 193 | + "execution_count": null, |
| 194 | + "metadata": {}, |
| 195 | + "outputs": [], |
| 196 | + "source": [ |
| 197 | + "from reactpy_jupyter import from_widget\n", |
| 198 | + "from ipywidgets import IntSlider\n", |
| 199 | + "\n", |
| 200 | + "slider_widget = IntSlider()\n", |
| 201 | + "slider_component = from_widget(slider_widget)\n", |
| 202 | + "\n", |
| 203 | + "slider_component" |
| 204 | + ] |
| 205 | + }, |
| 206 | + { |
| 207 | + "cell_type": "markdown", |
| 208 | + "metadata": {}, |
| 209 | + "source": [ |
| 210 | + "Let's consider a ReactPy component that responds to and displays changes from an `ipywidgets.IntSlider`. The ReactPy component will need to accept an `IntSlider` instance as one of its arguments, convert it to a component with `from_widget`, declare state that will track the slider's value, and register a lister that will update that state via the slider's `IntSlider.observe()` method using an [\"effect\"](https://reactpy.dev/docs/reference/hooks-api.html#use-effect):" |
190 | 211 | ]
|
191 | 212 | },
|
192 | 213 | {
|
|
198 | 219 | "outputs": [],
|
199 | 220 | "source": [
|
200 | 221 | "from reactpy import use_effect\n",
|
| 222 | + "from reactpy_jupyter import from_widget\n", |
201 | 223 | "\n",
|
202 | 224 | "\n",
|
203 | 225 | "@component\n",
|
204 | 226 | "def SliderObserver(slider):\n",
|
| 227 | + " slider_component = from_widget(slider)\n", |
205 | 228 | " value, set_value = use_state(0)\n",
|
206 | 229 | "\n",
|
207 | 230 | " @use_effect\n",
|
|
214 | 237 | " # unobserve the slider's value if this component is no longer displayed\n",
|
215 | 238 | " return lambda: slider.unobserve(handle_change, \"value\")\n",
|
216 | 239 | "\n",
|
217 |
| - " return html.p(f\"ReactPy observes the value to be: \", value)" |
| 240 | + " return html.div(slider_component, html.p(f\"ReactPy observes the value to be: \", value))" |
218 | 241 | ]
|
219 | 242 | },
|
220 | 243 | {
|
221 | 244 | "cell_type": "markdown",
|
222 | 245 | "metadata": {},
|
223 | 246 | "source": [
|
224 |
| - "Now you'll need to display the `SliderObserver` component as well as an `IntSlider` widget. To do this, you'll want wrap the component in a `reactpy_jupyter.LayoutWidget` instance before using it alongside other Jupyter Widgets. Specifically, you'll be displaying the `SliderObserver` and `IntSlider` in a `Box`:\n" |
| 247 | + "Now you need to pass the `SliderObserver` component an `IntSlider` widget and display it.\n" |
225 | 248 | ]
|
226 | 249 | },
|
227 | 250 | {
|
|
232 | 255 | },
|
233 | 256 | "outputs": [],
|
234 | 257 | "source": [
|
235 |
| - "from ipywidgets import Box, IntSlider\n", |
236 |
| - "from reactpy_jupyter import LayoutWidget\n", |
237 |
| - "\n", |
238 |
| - "slider = IntSlider(readout=False)\n", |
239 |
| - "slider_observer = LayoutWidget(SliderObserver(slider))\n", |
| 258 | + "from ipywidgets import IntSlider\n", |
240 | 259 | "\n",
|
241 |
| - "Box([slider, slider_observer])" |
| 260 | + "SliderObserver(IntSlider(readout=False))" |
242 | 261 | ]
|
243 | 262 | },
|
244 | 263 | {
|
245 | 264 | "cell_type": "markdown",
|
246 | 265 | "metadata": {},
|
247 | 266 | "source": [
|
248 |
| - "If it becomes painful to wrap every ReactPy component in a `LayoutWidget` you can create an alternate `LayoutWidget` constructor using `reactpy_jupyter.widgetize`:" |
| 267 | + "You can also include ReactPy components within Jupyter Widgets using `reactpy_jupyter.to_widget`" |
249 | 268 | ]
|
250 | 269 | },
|
251 | 270 | {
|
|
256 | 275 | },
|
257 | 276 | "outputs": [],
|
258 | 277 | "source": [
|
259 |
| - "from reactpy_jupyter import widgetize\n", |
260 |
| - "\n", |
261 |
| - "SliderObserverWidget = widgetize(SliderObserver)\n", |
| 278 | + "from ipywidgets import Box\n", |
| 279 | + "from reactpy_jupyter import to_widget\n", |
262 | 280 | "\n",
|
263 | 281 | "slider = IntSlider(readout=False)\n",
|
264 |
| - "slider_observer = SliderObserverWidget(slider)\n", |
| 282 | + "slider_observer_widget = to_widget(SliderObserver(slider))\n", |
265 | 283 | "\n",
|
266 |
| - "Box([slider, slider_observer])" |
| 284 | + "Box([slider, slider_observer_widget])" |
267 | 285 | ]
|
268 | 286 | },
|
269 | 287 | {
|
270 | 288 | "cell_type": "markdown",
|
271 | 289 | "metadata": {},
|
272 | 290 | "source": [
|
273 |
| - "It's worth noting that, while ReactPy can be used with Jupyter Widgets, the reverse is not true. That is, **you cannot use a Jupyter Widget inside a ReactPy component**. If this is a capability you would find useful, please [start a discussion](https://github.com/reactive-python/reactpy/discussions). The ReactPy team would be very interested to hear how allowing Jupyter Widgets to be used with ReactPy could facilitate your work." |
| 291 | + "If it becomes painful to convert every ReactPy component to a jupyter widget you can create an alternate widget constructor:" |
| 292 | + ] |
| 293 | + }, |
| 294 | + { |
| 295 | + "cell_type": "code", |
| 296 | + "execution_count": null, |
| 297 | + "metadata": {}, |
| 298 | + "outputs": [], |
| 299 | + "source": [ |
| 300 | + "slider = IntSlider(readout=False)\n", |
| 301 | + "slider_observer_constructor = to_widget(SliderObserver)\n", |
| 302 | + "observer_1 = slider_observer_constructor(slider)\n", |
| 303 | + "observer_2 = slider_observer_constructor(slider)\n", |
| 304 | + "\n", |
| 305 | + "Box([observer_1, observer_2])" |
274 | 306 | ]
|
275 | 307 | },
|
276 | 308 | {
|
|
0 commit comments