<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: JennaSys</title>
    <description>The latest articles on DEV Community by JennaSys (@jennasys).</description>
    <link>https://dev.to/jennasys</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F442592%2F4f52a835-de18-4aab-b331-d05d7fcbebbe.jpeg</url>
      <title>DEV Community: JennaSys</title>
      <link>https://dev.to/jennasys</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jennasys"/>
    <language>en</language>
    <item>
      <title>Setting up Hot Reload with KivyMD</title>
      <dc:creator>JennaSys</dc:creator>
      <pubDate>Tue, 02 Aug 2022 02:27:00 +0000</pubDate>
      <link>https://dev.to/jennasys/setting-up-hot-reload-with-kivymd-42h5</link>
      <guid>https://dev.to/jennasys/setting-up-hot-reload-with-kivymd-42h5</guid>
      <description>&lt;p&gt;The &lt;a href="https://kivymd.readthedocs.io/en/latest/"&gt;KivyMD&lt;/a&gt; hot reload feature allows you to make changes to the Python code and kvlang files in your &lt;a href="https://kivy.org"&gt;Kivy&lt;/a&gt; application and see the results in the running application without having to entirely stop and restart the application each time you make a change.  Many other application development platforms support this type of feature, so it is nice to see it is available for developing Kivy/KivyMD applications as well.&lt;/p&gt;

&lt;p&gt;But that said, I could not get it to work when I first tried using it.  At the time, I was already in the middle of developing an application and didn't want to get side-tracked, so I put off enabling the hot reload feature for another time.&lt;/p&gt;

&lt;p&gt;On my second try, I was determined to get it working with my now existing application.  Several tutorials and videos are available for getting hot reloading set up with Kivy, but even with that I still struggled to make it functional.  After reading documentation, digging into the code for the hot reload feature itself, watching a bunch of videos, reading several blog posts on the subject, and doing a lot of trial-and-error, I finally got it working.  In the end, it really wasn't that difficult to set up, but there were some seemingly minor details that kept me from getting it set up correctly on the first try, and it took me longer to get working than it should have.&lt;/p&gt;

&lt;p&gt;All that said, I'll document what I finally figured out here to hopefully help anyone who might fall into the same traps that I did.  I'm going to assume that anyone reading this is already familiar with the basics of Kivy/KivyMD, so I won't go into much detail on general project setup.  Instead, I will focus on just the specific changes that need to be made to enable the hot reload feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Good (Key points for getting it to work)
&lt;/h2&gt;

&lt;p&gt;The hot reload tool now built-in to KivyMD originated as a fork of &lt;a href="https://github.com/tito/kaki"&gt;Kaki&lt;/a&gt;.  Many of the tutorials on using hot reload with Kivy that you may find are based on that library, but most of the content in them applies to the KivyMD tool as well.&lt;/p&gt;

&lt;p&gt;Unlike the &lt;a href="https://pypi.org/project/kaki/"&gt;kaki&lt;/a&gt; Python library that automatically installs the dependencies it requires, with KivyMD you will need to &lt;code&gt;pip install&lt;/code&gt; the &lt;a href="https://pypi.org/project/watchdog/"&gt;watchdog&lt;/a&gt; library yourself if you use the KivyMD hot reload tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  MDApp import
&lt;/h3&gt;

&lt;p&gt;The first step in setting up your project for hot reloading, is to change where you import the &lt;code&gt;MDApp&lt;/code&gt; Kivy application instance from.  Typically, you would import &lt;code&gt;MDApp&lt;/code&gt; using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;kivymd.app&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MDApp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but to use the hot reload feature, you need to instead import &lt;code&gt;MDApp&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;kivymd.tools.hotreload.app&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MDApp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  MDApp.build_app() vs MDApp.build()
&lt;/h3&gt;

&lt;p&gt;This is one of the significant points that I had originally missed. While Kivy and KivyMD normally use the &lt;code&gt;build()&lt;/code&gt; method for initializing applications, the KivyMD hot reload tool (and Kaki) both instead use &lt;code&gt;build_app()&lt;/code&gt; to perform that function. All of the tutorials I saw did indeed use &lt;code&gt;build_app()&lt;/code&gt;, but that was a detail I had missed initially.&lt;/p&gt;

&lt;p&gt;But even after I realized this, I still had questions. Did it &lt;em&gt;replace&lt;/em&gt; the &lt;code&gt;build()&lt;/code&gt; method, or was it in &lt;em&gt;addition&lt;/em&gt; to the &lt;code&gt;build()&lt;/code&gt; method? Through trial-and-error and digging into the source code, I determined that it essentially replaced the &lt;code&gt;build()&lt;/code&gt; method that you would normally use. In fact, trying to override the &lt;code&gt;App.build()&lt;/code&gt; method like you typically would, generally resulted in just an empty screen being displayed.&lt;/p&gt;

&lt;p&gt;One side note about the &lt;code&gt;build_app()&lt;/code&gt; method, the signature of that method is slightly different, and it needs to accept an argument in its definition that the normal &lt;code&gt;build()&lt;/code&gt; method does not need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, the &lt;code&gt;build_app()&lt;/code&gt; method must also use the &lt;code&gt;ScreenManager&lt;/code&gt; object as its return value.&lt;/p&gt;

&lt;h3&gt;
  
  
  DEBUG
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;DEBUG&lt;/code&gt; is a class property that determines if the running instance should use the hot reload feature.  Almost every tutorial I saw insisted that you must start the application from the command line after setting this as an environment variable with &lt;code&gt;DEBUG=1&lt;/code&gt;.  Since I'm using PyCharm, I instead set it up as part of the run configuration for the project. What I didn't expect was that creating another run configuration with &lt;code&gt;DEBUG=0&lt;/code&gt; would still enable the hot reloading feature.  Instead, I had to leave the &lt;code&gt;DEBUG&lt;/code&gt; environment variable out of the non-debug run configuration altogether in order to actually disable hot reloading.&lt;/p&gt;

&lt;p&gt;You also have the option of hard coding the &lt;code&gt;DEBUG&lt;/code&gt; flag in your instance of &lt;code&gt;MDApp&lt;/code&gt;, or reading it from a &lt;em&gt;dotenv&lt;/em&gt; file and then dynamically setting it as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  KV_FILES, KV_DIRS &amp;amp; CLASSES
&lt;/h3&gt;

&lt;p&gt;Depending on how your project is set up and what you want the hot reload tool to watch, you need to populate these lists and/or dictionary as properties in your subclass implementation of &lt;code&gt;MDApp&lt;/code&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;KV_FILES&lt;/strong&gt;: &lt;em&gt;list[str]&lt;/em&gt;&lt;br&gt;
A list of relative or fully qualified file names for each kv file that you want to watch:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;KV_FILES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"./View/LoginScreen/login_screen.kv"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;KV_DIRS&lt;/strong&gt;: &lt;em&gt;list[str]&lt;/em&gt;&lt;br&gt;
A list of relative or fully qualified folder names for each directory containing kv files that you want to watch:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;KV_DIRS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"./View/LoginScreen"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CLASSES&lt;/strong&gt;: &lt;em&gt;dict[str:str]&lt;/em&gt;&lt;br&gt;
A dictionary of Python classes that you want to watch for changes. The dict key is the name of the class as a string, and the dict value is the module name as a string. For example, if you would normally import a particular class into a module, it might look like this:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;View.LoginScreen.login_screen&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Login&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;To define an analogous &lt;em&gt;CLASSES&lt;/em&gt; dictionary, you would create it like this:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;CLASSES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Login"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"View.LoginScreen.login_screen"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that you do not need to populate all three properties.  Just utilize the ones that make sense for how your project is organized, and for what you want to watch for changes that trigger the hot reload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;So, the tl;dr for enabling the KivyMD hot reload tool ends up being this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure the Python &lt;em&gt;watchdog&lt;/em&gt; library is installed &lt;/li&gt;
&lt;li&gt;Use the right &lt;code&gt;MDApp&lt;/code&gt; class&lt;/li&gt;
&lt;li&gt;Override the right build method&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;DEBUG&lt;/code&gt; property&lt;/li&gt;
&lt;li&gt;Populate the variables that tell hot reload what to watch for changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Bad (Dealing with maintenance hassles)
&lt;/h2&gt;

&lt;p&gt;Now that hot loading is working, I still didn't care for having to manually add classes and kv file names in the code every time I changed or added something.  It's a task that I'm sure I would repeatedly forget to do all the time.  So, I  added a few helper functions that would do that for me automatically at run time, eliminating the manual code maintenance.&lt;/p&gt;

&lt;p&gt;I already had a simple helper function that I was using for loading kv files where I would pass in the name of a module, and it would load a kv file by the same name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_kv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="n"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;module_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.kv"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the top of each view/screen module I created, I called this function, passing in the name of the current Python module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;load_kv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the hot loader tool manages loading and unloading kv files itself, I no longer needed to load them myself.  In fact, if I did, Kivy would give me warnings about the kv file being loaded multiple times.  I happen to know about this because I have personally seen them myself.  So I changed the helper function to add the kv file to the KV_FILES list instead of directly calling &lt;code&gt;Builder.load_file()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_kv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MDApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_running_app&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KV_FILES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;module_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.kv"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the classes, I added a helper method to the sub-classed &lt;code&gt;ScreenManager&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ScreenManager&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_classes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__class__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__class__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__module__&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screens&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It loops through the list of &lt;code&gt;screens&lt;/code&gt; that have been added to the &lt;code&gt;ScreenManager&lt;/code&gt; object using a dictionary comprehension, adding each &lt;code&gt;{class: module}&lt;/code&gt; to the dictionary.  Then in the &lt;code&gt;build_app()&lt;/code&gt; method, I call the &lt;code&gt;get_classes()&lt;/code&gt; method after instantiating the &lt;code&gt;ScreenManager&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;screen_manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SM&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;span class="n"&gt;CLASSES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;screen_manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_classes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these two functions, I no longer have to do any manual editing in order to make sure any changes to the application are being watched by the hot reload tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Ugly (Is it really worth it?)
&lt;/h2&gt;

&lt;p&gt;State management on a hot reload can be tricky. When a screen reloads, it may lose its state. This is particularly true if you are relying on the UI to hold state, like text in a &lt;code&gt;TextField&lt;/code&gt; widget. And then, non-UI state also needs to be considered. For example, what screen is currently being displayed, or whether the application is logged-in to a back-end REST server would need to be maintained. This may require you to rethink how state is updated and stored if you want to use hot reloading when developing your application.&lt;/p&gt;

&lt;p&gt;One possible solution, is to manually reload state after a hot reload. There is a generic &lt;code&gt;state&lt;/code&gt; object tied to the &lt;code&gt;MDApp&lt;/code&gt; class as a property and an &lt;code&gt;apply_state(state)&lt;/code&gt; method that gets called on every hot reload of the application. This method can be overridden to reapply any state that was lost due to the reload. However, as of right now, there is no hook implemented to give you a chance to save the application state before the hot reload starts.&lt;/p&gt;

&lt;p&gt;To use these state management features, you basically need to serialize the state of your application to the &lt;code&gt;MDApp.state&lt;/code&gt; object at the beginning of the rebuild process before the &lt;code&gt;ScreenManager&lt;/code&gt; gets restarted, and then deserialize the state back to your application in the &lt;code&gt;apply_state()&lt;/code&gt; method. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MDApp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="n"&gt;DEBUG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;  
    &lt;span class="n"&gt;sm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;  

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sm&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'current'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'one'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
                          &lt;span class="s"&gt;'one'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'data one'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
                          &lt;span class="s"&gt;'two'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'data two'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'current'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
                          &lt;span class="s"&gt;'one'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_screen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'one'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
                          &lt;span class="s"&gt;'two'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_screen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'two'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  

        &lt;span class="n"&gt;KV_FILES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;  
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SM&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
        &lt;span class="n"&gt;CLASSES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_classes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sm&lt;/span&gt;  

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'current'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_screen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'one'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'one'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_screen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'two'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'two'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I got around the current lack of a pre-reload hook for state by keeping my own reference to the &lt;code&gt;ScreenManager&lt;/code&gt; object as &lt;code&gt;self.sm&lt;/code&gt;. I pull the current state from that just before instantiating a new &lt;code&gt;ScreenManager&lt;/code&gt; and save it to the &lt;code&gt;MDApp.state&lt;/code&gt; object to be retrieved later in the &lt;code&gt;apply_state()&lt;/code&gt; method.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While the hot reloading feature is very convenient, I found that I had to modify my code in some ways that I wouldn’t otherwise have to, just to make it work well with hot reloading. In some cases, it made the code more complicated and subjectively less readable, in my opinion. Refactoring your code so that state is organized and well managed is obviously a good thing. However, there may be situations where it could also over-complicate what may otherwise be a simple application. So that said, while it’s a cool feature, hot reloading may not always be worth the hassle or extra tricks you have to do with the code to get it to work reliably and consistently.&lt;/p&gt;

&lt;p&gt;Links to working KivyMD projects demonstrating the hot reload configuration are included below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Kivy hot reload tool example code:&lt;br&gt;
&lt;a href="https://github.com/JennaSys/kivy_hotreload/tree/hotreload"&gt;https://github.com/JennaSys/kivy_hotreload/tree/hotreload&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code for a more complete(ish) Kivy Project with hot reload enabled:&lt;br&gt;
&lt;a href="https://github.com/JennaSys/kivy_rest/tree/hot-reload"&gt;https://github.com/JennaSys/kivy_rest/tree/hot-reload&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;KivyMD Hot Reload Tool Documentation:&lt;br&gt;
&lt;a href="https://kivymd.readthedocs.io/en/latest/api/kivymd/tools/hotreload/app"&gt;https://kivymd.readthedocs.io/en/latest/api/kivymd/tools/hotreload/app&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>kivy</category>
      <category>tutorial</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Using Parcel v2 and Transcrypt to create web applications with Python</title>
      <dc:creator>JennaSys</dc:creator>
      <pubDate>Mon, 07 Mar 2022 19:26:27 +0000</pubDate>
      <link>https://dev.to/jennasys/using-parcel-v2-and-transcrypt-to-create-web-applications-with-python-30ac</link>
      <guid>https://dev.to/jennasys/using-parcel-v2-and-transcrypt-to-create-web-applications-with-python-30ac</guid>
      <description>&lt;p&gt;When the &lt;a href="https://pyreact.com" rel="noopener noreferrer"&gt;&lt;em&gt;React to Python&lt;/em&gt;&lt;/a&gt; book was published, Parcel version 2 was just about to go into Beta.  Because of that, it was still a bit too volatile to include in the book.  But now that it is officially released, I thought I'd give those of you using Parcel as part of the toolchain I outlined in the book, a guide to using the newer version of Parcel.&lt;/p&gt;

&lt;p&gt;There are definitely some new features available in the latest version of Parcel that makes switching to it worthwhile.  To start with, the Parcel development server now supports server proxies, so you don't have to use an external proxy server to serve up your back-end REST services during the development process.  On top of that, the tree shaking algorithm is much more efficient at eliminating unused code from the generated JavaScript bundle, making the deployment bundle smaller.  Oh, and the builds are faster too!  Running a production build on the project in Part III of the &lt;em&gt;React to Python&lt;/em&gt; book resulted in a JavaScript bundle that was 30% smaller, and it took 15% less time to build.&lt;/p&gt;

&lt;p&gt;The general steps to modify an application to move from using the original version of Parcel to Parcel v2 are covered in the &lt;a href="https://parceljs.org/getting-started/migration/" rel="noopener noreferrer"&gt;Parcel v2 documentation&lt;/a&gt;.  Here, we'll go through the migration requirements in a little more detail from the perspective of a Python web application that utilizes the &lt;a href="https://www.transcrypt.org" rel="noopener noreferrer"&gt;Transcrypt&lt;/a&gt; Python-to-JavaScript transpiler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;The name of the NPM library for &lt;a href="https://www.npmjs.com/package/parcel" rel="noopener noreferrer"&gt;Parcel v2&lt;/a&gt; has changed from &lt;code&gt;parcel-bundler&lt;/code&gt; to &lt;code&gt;parcel&lt;/code&gt;.  So to install the Parcel v2 JavaScript library, use the following to install it as a development dependency:&lt;br&gt;&lt;br&gt;
$ &lt;code&gt;npm install parcel --save-dev&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;A new recently released &lt;a href="https://www.npmjs.com/package/parcel-transformer-transcrypt" rel="noopener noreferrer"&gt;Parcel plugin for Transcrypt&lt;/a&gt; that works with Parcel v2 can be installed with:&lt;br&gt;&lt;br&gt;
$ &lt;code&gt;npm install parcel-transformer-transcrypt --save-dev&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;For Parcel to know about the Transcrypt plugin, we need to add a &lt;em&gt;.parcelrc&lt;/em&gt; file in the same folder that the &lt;em&gt;package.json&lt;/em&gt; file resides in:  &lt;/p&gt;

&lt;p&gt;Listing 1: &lt;a href="https://github.com/JennaSys/rtp_demo/blob/parcel-v2/.parcelrc" rel="noopener noreferrer"&gt;&lt;em&gt;.parcelrc&lt;/em&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"@parcel/config-default"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"transformers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"*.py"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"parcel-transformer-transcrypt"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file tells Parcel that anytime it has a file with a &lt;code&gt;.py&lt;/code&gt; extension, that it should pass the file on to the Transcrypt plugin for processing.&lt;/p&gt;

&lt;p&gt;The Parcel CLI parameters have changed slightly compared to the previous version.  So upgrading an existing project to Parcel v2 may require you to update your NPM scripts in the &lt;em&gt;package.json&lt;/em&gt; file.&lt;/p&gt;

&lt;p&gt;Most notably, the &lt;code&gt;--log-level&lt;/code&gt; parameter now uses keywords instead of numbers, and the keyword for the output folder has changed from &lt;code&gt;--out-dir&lt;/code&gt; to &lt;code&gt;--dist-dir&lt;/code&gt;.   New scripts may look something more like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NODE_ENV=development parcel --log-level info src/index.html --dist-dir dist/dev --port 8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NODE_ENV=production parcel build --log-level info src/index.html --no-source-maps --dist-dir dist/prod --no-cache"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are using the Node.js &lt;code&gt;require()&lt;/code&gt; function in your source code to load static resources like images, you may also need to let Parcel know where to find those resource files at bundling time. If the path to the transpiled JavaScript files are no longer located relative to the source file folder after building, add an &lt;code&gt;"alias"&lt;/code&gt; entry to &lt;em&gt;package.json&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"./static/**"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/static/$1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This entry will tell Parcel that for any files that are supposed to be in a &lt;code&gt;static/&lt;/code&gt; folder in the current directory, to look for them in the &lt;code&gt;src/static/&lt;/code&gt; folder instead (relative to the root project folder).&lt;/p&gt;

&lt;h2&gt;
  
  
  Plugin Options
&lt;/h2&gt;

&lt;p&gt;The new Parcel plugin for Transcrypt works pretty much just like the one for the original version of Parcel, with a few additions.  The key new features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A configurable output folder (when using Transcrypt 3.9)&lt;/li&gt;
&lt;li&gt;The Parcel file watch works on  &lt;em&gt;all&lt;/em&gt;  transpiled Python files in development mode and not just the entry point&lt;/li&gt;
&lt;li&gt;It checks to make sure that the Python version matches the version of Transcrypt being used&lt;/li&gt;
&lt;li&gt;It doesn’t need patching before using it :-)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Like the previous version, it has a default configuration that can be overridden with an entry in the &lt;em&gt;package.json&lt;/em&gt; file for a project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"parcel-transformer-transcrypt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"transcryptVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3.9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"watchAllFiles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python -m transcrypt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"arguments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"--nomin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"--map"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"--verbose"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above configuration shows the default values that the Parcel Transcrypt plugin uses.  The &lt;code&gt;"transcryptVersion"&lt;/code&gt;, &lt;code&gt;"watchAllFiles"&lt;/code&gt;, &lt;code&gt;"command"&lt;/code&gt;, and &lt;code&gt;"arguments"&lt;/code&gt; keys are all optional.  Default values are used for any keys that are not supplied.&lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;watchAllFiles&lt;/code&gt; key is missing or set to &lt;code&gt;true&lt;/code&gt;, all Python files that Transcrypt processes will be added to Parcel’s file watch.  If this key is set to &lt;code&gt;false&lt;/code&gt;, only the initial entry point file will be watched. &lt;/p&gt;

&lt;p&gt;Transcrypt normally puts the files it generates in a folder called &lt;code&gt;__target__&lt;/code&gt;, which is created in the same folder as the source files you are processing.  This behavior may not be desirable if you prefer to keep your source code tree free of generated files.  &lt;/p&gt;

&lt;p&gt;By default, if you are using Transcrypt 3.9, the Parcel transformer will instead put Transcrypt's generated files in a folder named &lt;code&gt;.build&lt;/code&gt; that is created in the project's root folder (where the &lt;em&gt;package.json&lt;/em&gt; file resides and where you run &lt;code&gt;npm&lt;/code&gt; commands from).   You can override the location of this build folder by adding an argument to the above configuration as shown here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"arguments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"--nomin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"--map"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"--verbose"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"--outdir src/__target__"&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output folder you specify in the arguments should be relative to the project's root folder.  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that the &lt;code&gt;--outdir&lt;/code&gt; directive is not valid for Transcrypt version 3.7 and is ignored in that case.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Building a &lt;a href="https://github.com/JennaSys/rtp_demo/tree/parcel-v2" rel="noopener noreferrer"&gt;Python React demo application&lt;/a&gt; with Parcel v2 and the new Python plugin yields the following console output:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Findmpoidaqsbgy3yik2n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Findmpoidaqsbgy3yik2n.png" alt="Screenshot of parcel-transformer-transcrypt processing files"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Proxy Server
&lt;/h2&gt;

&lt;p&gt;One of the new features of Parcel v2 is the ability of its development server to act as a proxy for back-end data services like a REST API.  So now, instead of having to roll your own proxy server with &lt;code&gt;Express.js&lt;/code&gt; and the &lt;code&gt;http-proxy-middleware&lt;/code&gt; packages, you can configure Parcel to provide the same capability with no additional plugins required.&lt;/p&gt;

&lt;p&gt;To do so does require creating a simple &lt;em&gt;.proxyrc&lt;/em&gt; JSON configuration file:&lt;/p&gt;

&lt;p&gt;Listing 2: &lt;em&gt;.proxyrc&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"/api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8000/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pathRewrite"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"^/api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration would forward any requests having a URL starting with &lt;code&gt;/api&lt;/code&gt; to a backend server listening on port 8000, stripping off the &lt;code&gt;/api&lt;/code&gt; prefix in the process. For example, a request to &lt;code&gt;http://localhost:1234/api/getusers&lt;/code&gt; would be proxied to &lt;code&gt;http://localhost:8000/getusers&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Details
&lt;/h2&gt;

&lt;p&gt;The new version of Parcel does not automatically treat &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags as modules, so you must now explicitly specify them as such in order for imports to work correctly in a web browser. You can accomplish this by including a &lt;code&gt;type="module"&lt;/code&gt; attribute in the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag that loads the application entry point in the &lt;em&gt;index.html&lt;/em&gt; file as shown below:   &lt;/p&gt;

&lt;p&gt;Listing 3: &lt;a href="https://github.com/JennaSys/rtp_demo/blob/parcel-v2/.parcelrc" rel="noopener noreferrer"&gt;&lt;em&gt;index.html&lt;/em&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"app.py"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;React to Python&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of the changes that need to be made when upgrading from Parcel v1 to Parcel v2 happen in the &lt;em&gt;package.json&lt;/em&gt; file.  In addition to what was mentioned above, you may have a line like this in your &lt;em&gt;package.json&lt;/em&gt; file that was added by default when you ran &lt;code&gt;npm init&lt;/code&gt;:&lt;br&gt;&lt;br&gt;
&lt;code&gt;“main”: “index.js”&lt;/code&gt;&lt;br&gt;&lt;br&gt;
While that key was previously ignored in the older version of Parcel, the new version of Parcel will try and treat your web application as a library if it finds it there.  To keep Parcel v2 from complaining, that line will need to be removed.&lt;/p&gt;

&lt;h2&gt;
  
  
  tl;dr
&lt;/h2&gt;

&lt;p&gt;In summary, here are the basic changes needed when moving from Parcel v1 to Parcel v2 for Python web applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add  &lt;code&gt;type="module"&lt;/code&gt;  to entry point script tag in  &lt;em&gt;index.html&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Add  &lt;em&gt;.parcelrc&lt;/em&gt;  file to let Parcel know how to process &lt;code&gt;.py&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;Update  &lt;em&gt;package.json&lt;/em&gt;:

&lt;ul&gt;
&lt;li&gt;Remove key entry for &lt;code&gt;"main": "index.js"&lt;/code&gt; if it exists&lt;/li&gt;
&lt;li&gt;Update NPM scripts with new Parcel CLI parameters&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;"alias"&lt;/code&gt; key for relative static imports if necessary&lt;/li&gt;
&lt;li&gt;Update &lt;code&gt;"devDependencies"&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Change&lt;/em&gt; &lt;code&gt;parcel-bundler&lt;/code&gt; to &lt;code&gt;parcel&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Change&lt;/em&gt; &lt;code&gt;parcel-plugin-transcrypt&lt;/code&gt; to  &lt;code&gt;parcel-transformer-transcrypt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Change&lt;/em&gt; &lt;code&gt;parcel-plugin-bundle-visualiser&lt;/code&gt; to  &lt;code&gt;@parcel/reporter-bundle-analyzer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Remove&lt;/em&gt;  &lt;code&gt;express&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Remove&lt;/em&gt;  &lt;code&gt;http-proxy-middleware&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;If using a proxy server:

&lt;ul&gt;
&lt;li&gt;Add a &lt;em&gt;.proxyrc&lt;/em&gt; file with the backend server configuration&lt;/li&gt;
&lt;li&gt;Delete  &lt;em&gt;dev-server.js&lt;/em&gt;  and use  &lt;code&gt;npm start&lt;/code&gt;  instead of  &lt;code&gt;npm run dev&lt;/code&gt; for development&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;One of the admittedly annoying pain points of using the toolchain I outlined in the &lt;em&gt;React to Python&lt;/em&gt; book, was the fact that the Transcrypt plugin for Parcel was broken.  And because the plugin was not being actively maintained, it had to be patched after installing it. With Parcel v2 and the new Transcrypt plugin developed for it, this is no longer the case. Developing web applications with Python is now even more seamless and productive than it was before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Source Code:&lt;br&gt;
&lt;a href="https://github.com/JennaSys/rtp_demo/tree/parcel-v2" rel="noopener noreferrer"&gt;https://github.com/JennaSys/rtp_demo/tree/parcel-v2&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parcel Website:&lt;br&gt;
&lt;a href="https://parceljs.org/" rel="noopener noreferrer"&gt;https://parceljs.org/&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parcel v2 Migration Documentation:&lt;br&gt;
&lt;a href="https://parceljs.org/getting-started/migration/" rel="noopener noreferrer"&gt;https://parceljs.org/getting-started/migration/&lt;/a&gt;    &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parcel Plugin for Transcrypt:&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/parcel-transformer-transcrypt" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/parcel-transformer-transcrypt&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating React Applications with Python tutorial:&lt;br&gt;
&lt;a href="https://leanpub.com/rtptutorial" rel="noopener noreferrer"&gt;https://leanpub.com/rtptutorial&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;React to Python Book:&lt;br&gt;
&lt;a href="https://pyreact.com" rel="noopener noreferrer"&gt;https://pyreact.com&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transcrypt Site:&lt;br&gt;
&lt;a href="https://www.transcrypt.org" rel="noopener noreferrer"&gt;https://www.transcrypt.org&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>react</category>
      <category>webdev</category>
      <category>parcel</category>
    </item>
    <item>
      <title>Setting up a full-stack application on Replit</title>
      <dc:creator>JennaSys</dc:creator>
      <pubDate>Mon, 31 Jan 2022 18:45:55 +0000</pubDate>
      <link>https://dev.to/jennasys/setting-up-a-full-stack-application-on-replit-444e</link>
      <guid>https://dev.to/jennasys/setting-up-a-full-stack-application-on-replit-444e</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: The two example repls linked below that I created are currently broken thanks to the forced automated update to Nix  and not worth trying to fix at this point (I have nothing against Nix though). Quite frankly, Replit has become too slow, unstable, and poorly documented for me to justify using it anymore.&lt;/em&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thanks to a few programming tutorials I went through a while back, I was introduced to the &lt;a href="https://replit.com" rel="noopener noreferrer"&gt;Replit&lt;/a&gt; online development platform. More recently, I thought it would be an interesting exercise to see if I could use the Replit platform to host a development environment that I had been using for the Python-based approach to React development that I’ve adopted. I had outlined this approach in the &lt;a href="https://pyreact.com" rel="noopener noreferrer"&gt;&lt;em&gt;React to Python&lt;/em&gt;&lt;/a&gt; book and picked a few examples from the book to use as my test cases.&lt;/p&gt;

&lt;p&gt;While the Replit platform is pretty impressive, I went through quite a long learning curve in trying to figure out how to get all of the pieces I needed to use installed, configured, and running. In the end, I set up two separate repls using examples pulled right out of the book.&lt;/p&gt;

&lt;p&gt;The first was for a &lt;a href="https://github.com/JennaSys/replit_rtp_standalone" rel="noopener noreferrer"&gt;front-end-only application&lt;/a&gt; and was pretty straightforward to get set up.  But the second application was a &lt;a href="https://github.com/JennaSys/replit_rtp_fullstack" rel="noopener noreferrer"&gt;full-stack example&lt;/a&gt; and proved to be a bit more challenging to get configured.  Since it wasn't immediately obvious how to run multiple servers in a single Replit repl, I thought I'd document my solution here.  While my development stack may be a bit different than most, the approach here would still apply to many situations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replit basics
&lt;/h2&gt;

&lt;p&gt;Replit is kind of unique in the online development tool space since it provides you with many more options and more control over how you use it compared to most others I've seen.  You can get it working with just about every programming language out there, and for the more common ones, they have templates to get you started quickly.&lt;/p&gt;

&lt;p&gt;To create a new Replit project (or &lt;em&gt;repl&lt;/em&gt;), you select an appropriate template like Python, TypeScript, Rust, etc., and then start adding your source files.  If none of the available Replit templates are to your liking, you can also start with a Nix template that is essentially a blank slate to start building from.&lt;/p&gt;

&lt;p&gt;One of the main features of Replit is that repls created on that platform are easily forked.  This feature works much the same way as a public repository on GitHub might be forked.  Except that instead of just getting a copy of the source code, you are also getting a copy of the entire development environment that was created for it.  If your repl is public, even though your code is read-only to others, anyone can view it, fork it, and run it.&lt;/p&gt;

&lt;p&gt;One last way Replit gives you to create a repl, is to pull the project source code and Replit configuration directly from a GitHub repository.&lt;/p&gt;

&lt;p&gt;Within the Replit workspace, you have access to a file manager, code editor, Linux shell, Markdown viewer, and web browser window.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyttzciojkwv5rwed4fvz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyttzciojkwv5rwed4fvz.png" alt="Replit Workspace"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The basic setup
&lt;/h2&gt;

&lt;p&gt;A typical full-stack web application will have a public-facing front-end web server and a back-end application server that is used by and/or proxied by the front-end server. In my case, I was using Flask as a back-end server that had a very simple REST API, and then I had the &lt;a href="https://parceljs.org" rel="noopener noreferrer"&gt;Parcel bundler&lt;/a&gt; development proxy-server for the front-end.&lt;/p&gt;

&lt;p&gt;In addition to the servers, I also had a requirement to install and run a Python-to-JavaScript transpiler that is used in the build process.  This transpiler worked in conjunction with the Parcel bundler I was using.&lt;/p&gt;

&lt;p&gt;To automate setting up the development environment, I created a &lt;a href="https://github.com/JennaSys/replit_rtp_fullstack/blob/main/setup.sh" rel="noopener noreferrer"&gt;shell script&lt;/a&gt; that did the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installed the specific version of Python that I needed to use&lt;/li&gt;
&lt;li&gt;Installed &lt;a href="https://www.transcrypt.org" rel="noopener noreferrer"&gt;Transcrypt&lt;/a&gt; (the Python-to-JavaScript transpiler)&lt;/li&gt;
&lt;li&gt;Installed the JavaScript development and application dependencies for the project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also created a &lt;a href="https://github.com/JennaSys/replit_rtp_fullstack/blob/main/build.sh" rel="noopener noreferrer"&gt;shell script&lt;/a&gt; for starting the build process that will first check to make sure the required dependencies have been installed. If the dependencies are not installed, the build script will automatically run the setup script before running the &lt;code&gt;npm start&lt;/code&gt; script that starts the development server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running two servers
&lt;/h2&gt;

&lt;p&gt;If you know what you are looking for and where to look, the key to getting multiple servers working at the same time is in the &lt;a href="https://docs.replit.com/hosting/deploying-http-servers" rel="noopener noreferrer"&gt;Replit documentation&lt;/a&gt;.  But even then, what is provided there isn't completely clear and kind of sidesteps this particular issue a bit.&lt;/p&gt;

&lt;p&gt;An important key to getting the multi-server repl to work is understanding that the server started using a listening address of &lt;code&gt;0.0.0.0&lt;/code&gt; becomes the public-facing web server, and starting another server listening on &lt;code&gt;127.0.0.1&lt;/code&gt; keeps that server private.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;0.0.0.0&lt;/code&gt; is used, Replit accepts public requests to that server via one of its own publicly accessible IP addresses.  In addition to that, it also automatically enables SSL.  &lt;em&gt;Regardless of what port your server is listening on, the public-facing server will be accessed via the standard SSL port (443).&lt;/em&gt;  What this means is that, while you can use multiple ports for your internal servers, the public-facing server only accepts requests via the standard HTTPS port.&lt;/p&gt;

&lt;p&gt;Now that we have the back-end/front-end ports figured out, the next issue is how do you run both servers simultaneously?  Since both servers are blocking, you can't just chain start up commands, as the second server start command wouldn't execute until the first one ended.&lt;/p&gt;

&lt;p&gt;One option is to fork the first command and run it in the background, allowing the second one to execute.  While this works, you then don't have a convenient way of stopping the first command once you don't need it anymore.&lt;/p&gt;

&lt;p&gt;To solve this issue, I used the &lt;a href="https://www.npmjs.com/package/npm-run-all" rel="noopener noreferrer"&gt;&lt;code&gt;npm-run-all&lt;/code&gt;&lt;/a&gt; package.  This package allows you to run multiple npm scripts in parallel, and will exit out of all of them at the same time as well.&lt;/p&gt;

&lt;p&gt;My npm scripts in the &lt;a href="https://github.com/JennaSys/replit_rtp_fullstack/blob/main/package.json" rel="noopener noreferrer"&gt;&lt;em&gt;package.json&lt;/em&gt;&lt;/a&gt; file end up looking like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm-run-all -p -r flask-dev parcel-dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"flask-dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python main.py dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"parcel-dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NODE_ENV=development parcel --log-level info src/index.html --dist-dir dist/dev --port 8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NODE_ENV=production parcel build --log-level info src/index.html --no-source-maps --dist-dir dist/prod --no-cache"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Using &lt;code&gt;npm-run-all&lt;/code&gt;, the &lt;code&gt;npm start&lt;/code&gt; script then just calls two other scripts in parallel.  By using the &lt;code&gt;-r&lt;/code&gt; or &lt;code&gt;--race&lt;/code&gt; option, the process started by each of those scripts will be shut down when one of the other processes exits.&lt;/p&gt;

&lt;h2&gt;
  
  
  To build or not to build
&lt;/h2&gt;

&lt;p&gt;To run your application on Replit, there is a big shiny green &lt;em&gt;Run&lt;/em&gt; button at the top of the Replit workspace.  What this button actually does is defined by the Replit template used to create the repl, but it can also be customized in the &lt;a href="https://github.com/JennaSys/replit_rtp_fullstack/blob/main/.replit" rel="noopener noreferrer"&gt;&lt;em&gt;.replit&lt;/em&gt;&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;While it could make sense to have this button start up your development server, it may not be optimal.  Because of the way Replit works when someone else wants to view your application, they essentially click that same button. If your build process takes a while, they may give up on your application starting up before the build process finishes.&lt;/p&gt;

&lt;p&gt;So to facilitate faster startups in this situation, I prefer to just serve up pre-built application files directly with Flask when the &lt;em&gt;Run&lt;/em&gt; button is clicked, and perform the build process and running of the dev server from the command line instead.&lt;/p&gt;

&lt;p&gt;However, that means that the Flask server must be started up listening on different ports depending on if it is acting as the full-stack server, or if it's only acting as the back-end server. To achieve this, I added a conditional startup for Flask that is dependent on the existence of a command-line argument &lt;code&gt;dev&lt;/code&gt; when it is started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/JennaSys/replit_rtp_fullstack/blob/main/main.py" rel="noopener noreferrer"&gt;&lt;em&gt;main.py&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Start up flask in proxied mode if using parcel dev server
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dev&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Run public server
&lt;/span&gt;        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When Flask is started from the npm script as above:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"flask-dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python main.py dev"&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;it will use the &lt;code&gt;127.0.0.1&lt;/code&gt; address.  But when started using the Replit &lt;em&gt;Run&lt;/em&gt; button, it is configured in the &lt;em&gt;.replit&lt;/em&gt; file to call it without the additional argument:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="s"&gt;run = "python main.py"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;in which case it is started with the &lt;code&gt;0.0.0.0&lt;/code&gt; address.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;One general tip I can give for using Replit is to not fight their framework. Replit is opinionated in some of the tools they have pre-installed, and you are better off using what they have rather than ignoring them and just using what you may already be used to.  &lt;/p&gt;

&lt;p&gt;For example, in my case, I would typically set up a Python virtual environment using &lt;code&gt;venv&lt;/code&gt;, and then &lt;code&gt;pip&lt;/code&gt; install any Python dependencies I needed.  When I first tried that on Replit, the results were inconsistent at best.  When I went ahead and used the pre-installed Poetry package manager instead, everything went a lot smoother.&lt;/p&gt;

&lt;p&gt;While setting up a full-stack application on Replit isn't too difficult, figuring out exactly what needs to be done may not be immediately apparent.  Hopefully, my example here will give you some hints on how you might approach it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Replit website:&lt;br&gt;
&lt;a href="https://replit.com" rel="noopener noreferrer"&gt;https://replit.com&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;React to Python&lt;/em&gt; full-stack project source code:&lt;br&gt;
&lt;a href="https://github.com/JennaSys/replit_rtp_fullstack" rel="noopener noreferrer"&gt;https://github.com/JennaSys/replit_rtp_fullstack&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;React to Python&lt;/em&gt; full-stack example on Replit:&lt;br&gt;
&lt;a href="https://replit.com/@JennaSys/replitrtpfullstack" rel="noopener noreferrer"&gt;https://replit.com/@JennaSys/replitrtpfullstack&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parcel Bundler:&lt;br&gt;
&lt;a href="https://parceljs.org" rel="noopener noreferrer"&gt;https://parceljs.org&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating React Applications with Python tutorial:&lt;br&gt;
&lt;a href="https://leanpub.com/rtptutorial" rel="noopener noreferrer"&gt;https://leanpub.com/rtptutorial&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;React to Python&lt;/em&gt; Book:&lt;br&gt;
&lt;a href="https://pyreact.com" rel="noopener noreferrer"&gt;https://pyreact.com&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>parcel</category>
      <category>replit</category>
      <category>productivity</category>
    </item>
    <item>
      <title>No-el: Eliminate explicit calls to createElement() when using Python to code React applications</title>
      <dc:creator>JennaSys</dc:creator>
      <pubDate>Mon, 13 Dec 2021 03:12:57 +0000</pubDate>
      <link>https://dev.to/jennasys/no-el-eliminate-explicit-calls-to-createelement-when-using-python-to-code-react-applications-5214</link>
      <guid>https://dev.to/jennasys/no-el-eliminate-explicit-calls-to-createelement-when-using-python-to-code-react-applications-5214</guid>
      <description>&lt;p&gt;For those of you that have been utilizing the approach to creating React applications with Python from the &lt;a href="https://pyreact.com" rel="noopener noreferrer"&gt;&lt;em&gt;React to Python&lt;/em&gt;&lt;/a&gt; book, it may feel a bit kludgy having to call the &lt;code&gt;React.createElement()&lt;/code&gt; function all of the time.  But doing so is a necessity since JSX isn't a very practical option when using &lt;a href="https://www.transcrypt.org" rel="noopener noreferrer"&gt;Transcrypt&lt;/a&gt;.  Or perhaps having all of those &lt;code&gt;el()&lt;/code&gt;'s littering your code just makes things look a bit messier than you would prefer.  Well, I may have another option for you to try out that eliminates all of those &lt;code&gt;createElement()&lt;/code&gt; calls, yet doesn't really change the way you've been writing your Python React code all that much.&lt;/p&gt;

&lt;p&gt;Recently, a colleague was showing me some code they had written in &lt;a href="https://blog.jetbrains.com/kotlin/2021/05/technology-preview-jetpack-compose-for-web/" rel="noopener noreferrer"&gt;Jetpack Compose for Web&lt;/a&gt;, a toolkit by JetBrains which is based on Google’s platform for building reactive user interfaces with Kotlin.  It's not React, but it uses essentially the same paradigms as React.  One of the features that stood out to me when I was looking at their code was that, unlike React, the native HTML components were represented as actual component functions.  So, instead of creating React HTML elements like this as we have been doing in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;style&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;padding&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;12px&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello React!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where the HTML element is represented as a string, Jetpack Compose for Web treats HTML elements as first-class citizens and uses something more like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;Div&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nf"&gt;style&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello Jetpack!"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seeing that got me thinking: &lt;em&gt;"I wonder how difficult it would be to utilize that type of syntax in my own Python React projects?"&lt;/em&gt;  Going into it, I knew that I would want to accomplish two things in this challenge:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create wrapper functions for HTML elements so that React HTML components would be represented like any other functional React component.&lt;/li&gt;
&lt;li&gt;Create a Python decorator that wraps component functions with the call to &lt;code&gt;createElement()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Accomplishing these two goals would effectively eliminate the need to explicitly use &lt;code&gt;createElement()&lt;/code&gt; calls for generating every React element in a component tree.  Well, I'm happy to say that I accomplished both of those goals.  And it turns out that it wasn't even that difficult to do (I really do love Python!).  &lt;/p&gt;

&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;

&lt;p&gt;If you recall from the  &lt;a href="https://pyreact.com" rel="noopener noreferrer"&gt;&lt;em&gt;React to Python&lt;/em&gt;&lt;/a&gt; book or the &lt;a href="https://dev.to/jennasys/creating-react-applications-with-python-2je1"&gt;&lt;em&gt;Creating React Applications with Python&lt;/em&gt;&lt;/a&gt; tutorial, a module called  &lt;a href="https://github.com/JennaSys/rtp_demo/blob/main/pyreact.py" rel="noopener noreferrer"&gt;&lt;em&gt;pyreact.py&lt;/em&gt;&lt;/a&gt; is created to hold all of the code that bridges Python objects to the React JavaScript library.  It turns out that we only need to add a few more functions to this module to be able to eliminate all of the calls to &lt;code&gt;createElement()&lt;/code&gt; in the rest of our Python code.&lt;/p&gt;

&lt;p&gt;The heart of the entire solution is a single Python function that wraps a React component in a call to &lt;code&gt;createElement()&lt;/code&gt; and returns that as a new function.  It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;react_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;react_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;react_element&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have ever created a Python decorator, you may recognize the structure of this function.  In general terms, it is a function that takes a function as an argument and then returns a new function.  In this case, that returned function takes two (or more) arguments: &lt;code&gt;props&lt;/code&gt; and zero or more &lt;code&gt;children&lt;/code&gt;.  The return value of the new function is just the call to &lt;code&gt;React.createElement()&lt;/code&gt; that is used in the usual way.&lt;/p&gt;

&lt;p&gt;We will use this function in two ways.  Even though this function is structured like a decorator, there is nothing to keep us from also calling it directly.  Thanks to the dynamic nature of Python, the &lt;code&gt;component&lt;/code&gt; that we pass into this function doesn't even necessarily &lt;em&gt;have&lt;/em&gt; to be a function.  In fact, it can even be a string.  This feature allows us to handle the first part of our challenge in turning React HTML elements into functional components :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;Div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;react_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The string &lt;code&gt;'div'&lt;/code&gt; that is passed into the function gets used as the first parameter in the call to &lt;code&gt;createElement()&lt;/code&gt; in the generated function.  This is just like we were previously using it in our own Python React code.  We then save the return value of the call to &lt;code&gt;react_component('div')&lt;/code&gt; in a variable called &lt;code&gt;Div&lt;/code&gt; which now contains the newly generated wrapped function.&lt;/p&gt;

&lt;p&gt;Putting all of this together, the additional code we end up adding to the updated &lt;a href="https://github.com/JennaSys/rtp_demo/blob/no-el/pyreact.py" rel="noopener noreferrer"&gt;&lt;em&gt;pyreact.py&lt;/em&gt;&lt;/a&gt; module then looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;react_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;react_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;react_element&lt;/span&gt;

&lt;span class="n"&gt;Form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;react_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;form&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;react_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;label&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="n"&gt;Input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;react_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="n"&gt;Ol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;react_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ol&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="n"&gt;Li&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;react_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;li&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="n"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;react_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;button&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="n"&gt;Div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;react_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="n"&gt;Span&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;react_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;span&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, creating function wrappers for other React HTML elements becomes a trivial task.  Now that we have that in place, we'll next take a look at how these new functions simplify the code we use to create our React applications by eliminating the need to explicitly call &lt;code&gt;createElement()&lt;/code&gt; every time ourselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  An Example
&lt;/h2&gt;

&lt;p&gt;Starting with the &lt;a href="https://github.com/JennaSys/rtp_demo" rel="noopener noreferrer"&gt;React code from the tutorial&lt;/a&gt;, we add the necessary wrapper functions to &lt;a href="https://github.com/JennaSys/rtp_demo/blob/no-el/pyreact.py" rel="noopener noreferrer"&gt;&lt;em&gt;pyreact.py&lt;/em&gt;&lt;/a&gt; as above and then refactor the demo application to remove the calls to &lt;code&gt;createElement()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Listing 1: &lt;a href="https://github.com/JennaSys/rtp_demo/blob/no-el/app.py" rel="noopener noreferrer"&gt;&lt;em&gt;app.py&lt;/em&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pyreact&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;react_component&lt;/span&gt;  
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pyreact&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Li&lt;/span&gt;  


&lt;span class="nd"&gt;@react_component&lt;/span&gt;  
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ListItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;items&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Li&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;  
    &lt;span class="n"&gt;newItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setNewItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;  

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
        &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
        &lt;span class="c1"&gt;# setItems(items.__add__(newItem))  
&lt;/span&gt;        &lt;span class="nf"&gt;setItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;newItem&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# __:opov  
&lt;/span&gt;        &lt;span class="nf"&gt;setNewItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
        &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;target&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
        &lt;span class="nf"&gt;setNewItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;onSubmit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  
                &lt;span class="nc"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;htmlFor&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;newItem&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New Item: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
                &lt;span class="nc"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;newItem&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
                       &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;onChange&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
                       &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;newItem&lt;/span&gt;  
                       &lt;span class="p"&gt;}&lt;/span&gt;  
                      &lt;span class="p"&gt;),&lt;/span&gt;  
                &lt;span class="nc"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;submit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;  
                &lt;span class="nc"&gt;Ol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
                   &lt;span class="nc"&gt;ListItems&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;items&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;  
                   &lt;span class="p"&gt;)&lt;/span&gt;  
                &lt;span class="p"&gt;)&lt;/span&gt;  


&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing you may notice about this refactored code is that there are no calls to &lt;code&gt;createElement()&lt;/code&gt; in sight!  Removing all of those &lt;code&gt;el()&lt;/code&gt;'s from the &lt;a href="https://github.com/JennaSys/rtp_demo/blob/main/app.py" rel="noopener noreferrer"&gt;original version of  &lt;em&gt;app.py&lt;/em&gt;&lt;/a&gt; has cleaned up the code quite a bit.&lt;/p&gt;

&lt;p&gt;Now that we're not basing the HTML components on strings, we do have to import the ones we use in the module as we did here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pyreact&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Li&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;import&lt;/code&gt; line above that one, we also imported the new &lt;code&gt;react_component()&lt;/code&gt; function that we created in the &lt;em&gt;pyreact.py&lt;/em&gt; module.  Here, we now use this as a decorator for any React functional components that we create. When we do, they will also get wrapped by the call to &lt;code&gt;createElement()&lt;/code&gt; when the component gets rendered by React.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@react_component&lt;/span&gt;  
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ListItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;items&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Li&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A side-benefit of using this decorator, is that it now becomes very easy to tell which of your Python function definitions are React components and which are just plain functions.&lt;/p&gt;

&lt;p&gt;In this code block, you can also see the first use of our new HTML components that we use in place of the explicit call to &lt;code&gt;createElement()&lt;/code&gt;.  So instead of using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;li&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where the HTML element is identified by a string as we did before, we now use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nc"&gt;Li&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where the HTML element is a functional component itself.&lt;/p&gt;

&lt;p&gt;The other changes we made were all in the return statement that builds the component tree.  Here, all of the calls to &lt;code&gt;createElement()&lt;/code&gt; were replaced by their functional component counterparts.  All of the props and the child component structure aspects remained exactly the same as they were before making the changes.&lt;/p&gt;

&lt;p&gt;For instructions on preparing the development environment and running the code we discussed here, you can reference the &lt;a href="https://dev.to/jennasys/creating-react-applications-with-python-2je1"&gt;original tutorial&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7z10y3djzpafwehow77.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7z10y3djzpafwehow77.png" alt="React App Screenshot" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While it is definitely subjective, for me, calling &lt;code&gt;React.createElement()&lt;/code&gt; when aliased as &lt;code&gt;el()&lt;/code&gt; in my Python code is but a small concession for not having JSX available to use in the Python modules.  In all honesty, it never really bothered me all that much.  But for larger components, having all of those &lt;code&gt;el()&lt;/code&gt;'s cluttering up the Python code can tend to impact readability a bit.  By encapsulating the call to &lt;code&gt;createElement()&lt;/code&gt; in the component itself, we can avoid having to explicitly call it in our Python code when building the element tree.&lt;/p&gt;

&lt;p&gt;One drawback to eliminating the explicit calls to &lt;code&gt;createElement()&lt;/code&gt; is that it might not be quite as evident as to what parts of your Python code are creating React elements versus just making regular function calls.  Another possible downside might be that this encapsulation of the element creation could be seen as moving away from the mental model of how React actually works.  These points are both very subjective, so you will have to decide for yourself if it makes sense to use what I've described here.&lt;/p&gt;

&lt;p&gt;On the plus side, now that we've eliminated some of the &lt;code&gt;createElement()&lt;/code&gt; code clutter, I feel that this approach makes it even less of an issue that we are not using JSX for creating React applications.  Additionally, by using defined functions instead of strings for creating HTML components, the IDE is able to help us out a little bit better when coding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Source Code:&lt;br&gt;
&lt;a href="https://github.com/JennaSys/rtp_demo/tree/no-el" rel="noopener noreferrer"&gt;https://github.com/JennaSys/rtp_demo/tree/no-el&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Original Source Code:&lt;br&gt;
&lt;a href="https://github.com/JennaSys/rtp_demo" rel="noopener noreferrer"&gt;https://github.com/JennaSys/rtp_demo&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transcrypt Site:&lt;br&gt;
&lt;a href="https://www.transcrypt.org" rel="noopener noreferrer"&gt;https://www.transcrypt.org&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Jetpack Compose for Web:&lt;br&gt;
&lt;a href="https://compose-web.ui.pages.jetbrains.team" rel="noopener noreferrer"&gt;https://compose-web.ui.pages.jetbrains.team&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating React Applications with Python tutorial:&lt;br&gt;
&lt;a href="https://leanpub.com/rtptutorial" rel="noopener noreferrer"&gt;https://leanpub.com/rtptutorial&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;React to Python Book:&lt;br&gt;
&lt;a href="https://pyreact.com" rel="noopener noreferrer"&gt;https://pyreact.com&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>react</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Creating React Applications with Python</title>
      <dc:creator>JennaSys</dc:creator>
      <pubDate>Mon, 21 Jun 2021 17:44:55 +0000</pubDate>
      <link>https://dev.to/jennasys/creating-react-applications-with-python-2je1</link>
      <guid>https://dev.to/jennasys/creating-react-applications-with-python-2je1</guid>
      <description>&lt;h2&gt;
  
  
  Full-Stack Python
&lt;/h2&gt;

&lt;p&gt;Let me start by getting this out of the way: &lt;em&gt;I really like programming in Python, and I'm not a big fan of JavaScript.&lt;/em&gt;  But let’s face it, JavaScript is the way of the web, and Python doesn’t run in a web browser.  So end of story, right?  Well not so fast, because just like the popular TypeScript language gets transpiled into JavaScript to run in a web browser, &lt;a href="https://www.transcrypt.org" rel="noopener noreferrer"&gt;Transcrypt&lt;/a&gt; does the same thing for Python.&lt;/p&gt;

&lt;p&gt;Because of the way Transcrypt maps Python data types and language constructs to JavaScript, your Python code is able to utilize the full ecosystem of JavaScript libraries that exist.  Transcrypt acts as a bridge that enables you to take advantage of existing JavaScript web application technologies rather than trying to reinvent them.  And, it does it in a way that doesn't significantly affect application performance over using plain JavaScript, or that requires a large runtime module to be downloaded to the client.  And though we &lt;em&gt;use&lt;/em&gt; JavaScript libraries, we don't have to code in JavaScript to use their APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features of Transcrypt include:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It's PIP installable&lt;/li&gt;
&lt;li&gt;Python code is transpiled to JavaScript before being deployed&lt;/li&gt;
&lt;li&gt;It uses a very small JavaScript runtime (~40K)&lt;/li&gt;
&lt;li&gt;It can generate sourcemaps for troubleshooting Python in the browser&lt;/li&gt;
&lt;li&gt;The generated JavaScript is human-readable&lt;/li&gt;
&lt;li&gt;The generated JavaScript can be minified&lt;/li&gt;
&lt;li&gt;Performance is comparable to native JavaScript&lt;/li&gt;
&lt;li&gt;It maps Python data types and language constructs to JavaScript&lt;/li&gt;
&lt;li&gt;It acts as a bridge between the Python and JavaScript worlds&lt;/li&gt;
&lt;li&gt;It supports almost all Python built-ins and language constructs&lt;/li&gt;
&lt;li&gt;It only has limited support for the Python standard library&lt;/li&gt;
&lt;li&gt;Your Python code can “directly” call JavaScript functions&lt;/li&gt;
&lt;li&gt;Native JavaScript can call your Python functions&lt;/li&gt;
&lt;li&gt;It only supports 3rd party Python libraries that are pure Python&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  npm instead of pip
&lt;/h3&gt;

&lt;p&gt;Most Python language constructs and built-ins have been implemented in Transcrypt, so working with standard Python objects like lists, dictionaries, strings, and more will feel just like Python should.  Generally speaking however, third-party Python libraries are not supported unless the library (and its dependencies) are pure Python.&lt;/p&gt;

&lt;p&gt;What this means is that instead of turning to &lt;code&gt;urllib&lt;/code&gt; or the &lt;code&gt;requests&lt;/code&gt; library when you need to make an HTTP request from your web browser application, you would utilize &lt;code&gt;window.fetch()&lt;/code&gt; or the JavaScript &lt;code&gt;axios&lt;/code&gt; library instead.  But you would still code to those JavaScript libraries using Python.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Getting started with Transcrypt is pretty easy.  Ideally, you would want to create a Python virtual environment for your project, activate it, and then use PIP to install Transcrypt.  Transcrypt currently supports Python 3.9 or Python 3.7 so you will need to create your virtual environment with one of those versions, and then install the appropriate version of Transcrypt:&lt;/p&gt;

&lt;p&gt;$ &lt;code&gt;python3.9 -m venv venv&lt;/code&gt;&lt;br&gt;
or&lt;br&gt;
$ &lt;code&gt;python3.7 -m venv venv&lt;/code&gt;&lt;br&gt;&lt;br&gt;
 &lt;br&gt;
$ &lt;code&gt;source venv/bin/activate&lt;/code&gt;&lt;br&gt;
(for Windows use &lt;code&gt;venv\Scripts\activate&lt;/code&gt; )&lt;br&gt;&lt;br&gt;
 &lt;br&gt;
(venv) $ &lt;code&gt;pip install transcrypt==3.9&lt;/code&gt;&lt;br&gt;
or&lt;br&gt;
(venv) $ &lt;code&gt;pip install transcrypt==3.7.16&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Hello World
&lt;/h2&gt;

&lt;p&gt;With Transcrypt installed, we can try a simple &lt;em&gt;Hello World&lt;/em&gt; web application to see how it works.  We'll create two files:  a Python file with a few functions, and an HTML file that we will open up in a web browser:&lt;/p&gt;

&lt;p&gt;Listing 1: &lt;a href="https://github.com/JennaSys/rtp_demo/blob/main/hello.py" rel="noopener noreferrer"&gt;&lt;em&gt;hello.py&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;destination&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello World!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clear_it&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;destination&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Listing 2: &lt;a href="https://github.com/JennaSys/rtp_demo/blob/main/hello.html" rel="noopener noreferrer"&gt;&lt;em&gt;hello.html&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clear_it&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./__target__/hello.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sayBtn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;clearBtn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;clear_it&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"sayBtn"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click Me!&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"clearBtn"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Clear&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"destination"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We then transpile the Python file with the Transcrypt CLI:&lt;br&gt;&lt;br&gt;
(venv) $ &lt;code&gt;transcrypt --nomin --map hello&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here, we passed the &lt;code&gt;transcrypt&lt;/code&gt; command three arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--nomin&lt;/code&gt; turns off minification to leave the generated code in a human-readable format&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--map&lt;/code&gt; generates sourcemaps for debugging Python code in the web browser&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hello&lt;/code&gt; is the name of python module to transpile&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can serve up the &lt;em&gt;Hello World&lt;/em&gt; application using the built-in Python HTTP server:&lt;br&gt;&lt;br&gt;
(venv) $ &lt;code&gt;python -m http.server&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This starts up a webserver that serves up files in the current directory, from which we can open our HTML file at:&lt;br&gt;&lt;br&gt;
&lt;a href="http://localhost:8000/hello.html" rel="noopener noreferrer"&gt;http://localhost:8000/hello.html&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FJennaSys%2Frtp_demo%2Fraw%2Fmain%2Fimages%2Fhello_screenshot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FJennaSys%2Frtp_demo%2Fraw%2Fmain%2Fimages%2Fhello_screenshot.png" alt="Hello World Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see with this simple demonstration, we have Python calling methods of JavaScript objects using Python syntax, and JavaScript calling "Python" functions that have been transpiled.  And as mentioned earlier, the generated JavaScript code is quite readable:&lt;/p&gt;

&lt;p&gt;Listing 3 (Generated code): &lt;em&gt;__target__/hello.js&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Transcrypt'ed from Python&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./org.transcrypt.__runtime__.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;__main__&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;say_hello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
   &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;destination&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;};&lt;/span&gt;  
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;clear_it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
   &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;destination&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;};&lt;/span&gt;  

&lt;span class="c1"&gt;//# sourceMappingURL=hello.map&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Sourcemaps
&lt;/h2&gt;

&lt;p&gt;To demonstrate the sourcemap feature, we can again create two source files: a Python file with a function to be transpiled, and an HTML file that will be the entry point for our application in the web browser.  This time, our Python file will have a function that outputs text to the web browser console using both JavaScript and Python methods, along with a JavaScript method call that will generate an error at runtime:&lt;/p&gt;

&lt;p&gt;Listing 4: &lt;a href="https://github.com/JennaSys/rtp_demo/blob/main/sourcemap.py" rel="noopener noreferrer"&gt;&lt;em&gt;sourcemap.py&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_stuff&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Native JS console.log call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python print&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invalid_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This will be an error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Listing 5: &lt;a href="https://github.com/JennaSys/rtp_demo/blob/main/sourcemap.html" rel="noopener noreferrer"&gt;&lt;em&gt;sourcemap.html&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;print_stuff&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./__target__/sourcemap.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;printBtn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;print_stuff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"printBtn"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Print&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;(venv) $ &lt;code&gt;transcrypt --nomin --map sourcemap&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This time, with the built-in Python HTTP server started using:&lt;br&gt;&lt;br&gt;
(venv) $ &lt;code&gt;python -m http.server&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can open our test application at:&lt;br&gt;&lt;br&gt;
&lt;a href="http://localhost:8000/sourcemap.html" rel="noopener noreferrer"&gt;http://localhost:8000/sourcemap.html&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FJennaSys%2Frtp_demo%2Fraw%2Fmain%2Fimages%2Fsourcemap_screenshot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FJennaSys%2Frtp_demo%2Fraw%2Fmain%2Fimages%2Fsourcemap_screenshot.png" alt="Sourcemap Error Screenshot"&gt;&lt;/a&gt;&lt;br&gt;
If you open the developer console in the web browser and then click the button, the first two calls will execute, printing the text to the web browser console.  The call to the JavaScript &lt;code&gt;console.log()&lt;/code&gt; method behaves as you would expect.  But as you can see here, the Python &lt;code&gt;print()&lt;/code&gt; function ends up getting transpiled to call the JavaScript &lt;code&gt;console.log()&lt;/code&gt; method as well.&lt;/p&gt;

&lt;p&gt;The third function call generates an error since we are trying to call a nonexistent method of the JavaScript &lt;code&gt;console&lt;/code&gt; object.  However, what's nice in this case is that the sourcemap can direct us to the cause of the problem in our &lt;em&gt;Python&lt;/em&gt; source file.  So, even though it is the generated JavaScript that is actually running in the web browser, using a sourcemap, we can still view our Python code right in the web browser and see where the error occurred in the Python file as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FJennaSys%2Frtp_demo%2Fraw%2Fmain%2Fimages%2Fsourcemap2_screenshot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FJennaSys%2Frtp_demo%2Fraw%2Fmain%2Fimages%2Fsourcemap2_screenshot.png" alt="Sourcemap Python Code Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  React
&lt;/h2&gt;

&lt;p&gt;Now that we've seen how Transcrypt lets us make calls to JavaScript, let's step it up and use Transcrypt to make calls to the React library.  We'll start with another simple &lt;em&gt;Hello World&lt;/em&gt; application again, but this time doing it the React way.  We'll stick with the two source files: a python file to be transpiled and an HTML file that will be opened in a web browser.  The HTML file will be doing a little extra work for us in that it will be responsible for loading the React JavaScript libraries.&lt;/p&gt;

&lt;p&gt;Listing 6: &lt;a href="https://github.com/JennaSys/rtp_demo/blob/main/hello_react.py" rel="noopener noreferrer"&gt;&lt;em&gt;hello_react.py&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;useState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;useState&lt;/span&gt;
&lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createElement&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setVal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="nf"&gt;setVal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello React!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clear_it&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="nf"&gt;setVal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;button&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;say_hello&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Click Me!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;button&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;clear_it&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Clear&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Listing 7: &lt;a href="https://github.com/JennaSys/rtp_demo/blob/main/hello_react.html" rel="noopener noreferrer"&gt;&lt;em&gt;hello_react.html&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;crossorigin&lt;/span&gt;
      &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/react@16/umd/react.production.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;crossorigin&lt;/span&gt;
      &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"__target__/hello_react.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now transpile the Python file with Transcrypt:&lt;br&gt;&lt;br&gt;
(venv) $ &lt;code&gt;transcrypt --nomin --map hello_react&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;Once again, after Transcrypt is done generating the JavaScript files, start up the built-in Python HTTP server using:  &lt;/p&gt;

&lt;p&gt;(venv) $ &lt;code&gt;python -m http.server&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;Then open the demo React application at:&lt;br&gt;&lt;br&gt;
&lt;a href="http://localhost:8000/hello_react.html" rel="noopener noreferrer"&gt;http://localhost:8000/hello_react.html&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FJennaSys%2Frtp_demo%2Fraw%2Fmain%2Fimages%2Fhelloreact_screenshot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FJennaSys%2Frtp_demo%2Fraw%2Fmain%2Fimages%2Fhelloreact_screenshot.png" alt="Hello React Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While functionally the same as the first demo application we did, this time React adds dynamically generated HTML as a child of a specified element - in this case, the "root" &lt;code&gt;div&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here, we added some convenience variables, &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;el&lt;/code&gt;, to map the global React methods to local Python variables.  The React &lt;code&gt;createElement()&lt;/code&gt; method is the workhorse of the library and is used to generate HTML elements in the browser dynamically.&lt;/p&gt;

&lt;p&gt;React is declarative, functional, and is based on state.  What this means, is that you define the view, and then React handles when and how it gets updated when there are changes in state.  By design, React state variables are immutable and use a setter function to make updates.  This helps React to know when changes to state occur, so it can then re-render the view as needed.  In this example, we used the React &lt;code&gt;useState()&lt;/code&gt; method to create the &lt;code&gt;val&lt;/code&gt; variable and its corresponding &lt;code&gt;setVal()&lt;/code&gt; setter function.&lt;/p&gt;

&lt;p&gt;The return statement of a React functional component generally consists of a number of nested and chained calls to the React &lt;code&gt;createElement()&lt;/code&gt; function that collectively form a tree structure of HTML elements and/or React components.  This is where the view is declaratively defined.  It may take some time to get more comfortable with this if you are not used to doing functional programming in Python.&lt;/p&gt;

&lt;p&gt;The ReactDOM &lt;code&gt;render()&lt;/code&gt; function takes the top-level React component and a reference to the HTML element to attach it to in the DOM.  This is where it adds the dynamically generated HTML tree that React produces as a child of the specified element.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Building a React Application
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: The Parcel bundler has recently been updated and there is now a new version of the &lt;a href="https://www.npmjs.com/package/parcel-transformer-transcrypt" rel="noopener noreferrer"&gt;Transcrypt plug-in for Parcel v2&lt;/a&gt; that eliminates the patch requirements outlined below. See the &lt;a href="https://dev.to/jennasys/using-parcel-v2-and-transcrypt-to-create-web-applications-with-python-30ac"&gt;Using Parcel v2 and Transcrypt&lt;/a&gt; blog post for details on how to implement that version. The instructions provided below still apply if using the older version of Parcel.&lt;/em&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Having done a simple React application, let's now create one that has a few more moving parts.  This demo will take a value entered through the UI and add it to a list when submitted.&lt;/p&gt;

&lt;p&gt;Most web applications of any utility will get large enough to where it becomes too unwieldy to manage manually.  This is where package managers and application bundlers come into play.  For this next example, we'll use the Parcel bundler to build and bundle the application so you can see what this developer stack might look like for larger applications.&lt;/p&gt;

&lt;p&gt;First, we need to install the necessary JavaScript libraries to support the development toolchain.  This does require &lt;a href="https://nodejs.org/en/download/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; to be installed on your system so that we can use the Node Package Manager.  We start by initializing a new project and installing the Parcel bundler library along with the plug-in for Transcrypt:&lt;/p&gt;

&lt;p&gt;$ &lt;code&gt;npm init -y&lt;/code&gt;&lt;br&gt;&lt;br&gt;
$ &lt;code&gt;npm install parcel-bundler --save-dev&lt;/code&gt;&lt;br&gt;&lt;br&gt;
$ &lt;code&gt;npm install parcel-plugin-transcrypt --save-dev&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;Then we can install the React libraries:&lt;br&gt;&lt;br&gt;
$ &lt;code&gt;npm install react@16 react-dom@16&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;Because of a version incompatibility, there is a file in the current Transcrypt plug-in that requires a patch.  The file in question is:&lt;br&gt;&lt;br&gt;
 &lt;strong&gt;./node_modules/parcel-plugin-transcrypt/asset.js&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;In that file, change line 2 that loads the Parcel &lt;code&gt;Logger&lt;/code&gt; module from this:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;parcel-bundler/src/Logger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;to this:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@parcel/logger/src/Logger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once this modification is made to change the location of the Parcel &lt;code&gt;Logger&lt;/code&gt; module, the Transcrypt plug-in for Parcel should be working.  &lt;/p&gt;




&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE FOR WINDOWS USERS:&lt;/em&gt;&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;For those of you using Windows, two more changes need to be made to the &lt;strong&gt;asset.js&lt;/strong&gt; file for it to work in Windows environments.  The first is to modify the default Transcrypt build configuration to just use the version of Python that you set your virtual environment up with.  &lt;/p&gt;

&lt;p&gt;To do that, change line 14 that defines the Transcrypt command to simply use &lt;code&gt;python&lt;/code&gt; instead of &lt;code&gt;python3&lt;/code&gt;, changing it from this:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;command&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;python3 -m transcrypt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;to this:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;command&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;python -m transcrypt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The second change has to do with modifying an import file path so that it uses Windows-style back-slashes instead of the Linux/Mac style forward-slashes.  For this modification, we can use a string &lt;code&gt;replace()&lt;/code&gt; method on line 143 to make an inline correction to the file path for Windows environments.  So change this line:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`export * from "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;importPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;";`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;to this:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`export * from "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;importPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;";`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;At some point, I would expect that a modification will be incorporated into the parcel-plugin-transcrypt package so that this hack can be avoided in the future.&lt;/p&gt;




&lt;p&gt;Now that we have a bundler in place, we have more options as to how we work with JavaScript libraries.  For one, we can now take advantage of the Node &lt;code&gt;require()&lt;/code&gt; function that allows us to control the namespace that JavaScript libraries get loaded into.   We will use this to isolate our Python-to-JavaScript mappings to one module, which keeps the rest of our code modules all pure Python.&lt;/p&gt;

&lt;p&gt;Listing 8: &lt;a href="https://github.com/JennaSys/rtp_demo/blob/main/pyreact.py" rel="noopener noreferrer"&gt;&lt;em&gt;pyreact.py&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# __pragma__ ('skip')
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lib&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;document&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;getElementById&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;addEventListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="c1"&gt;# __pragma__ ('noskip')
&lt;/span&gt;
&lt;span class="c1"&gt;# Load React and ReactDOM JavaScript libraries into local namespace
&lt;/span&gt;&lt;span class="n"&gt;React&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;react&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ReactDOM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;react-dom&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Map React javaScript objects to Python identifiers
&lt;/span&gt;&lt;span class="n"&gt;createElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createElement&lt;/span&gt;
&lt;span class="n"&gt;useState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;useState&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root_component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Loads main react component into DOM&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root_component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;At the top of the file, we used one of Transcrypt's &lt;code&gt;__pragma__&lt;/code&gt; compiler directives to tell it to ignore the code between the &lt;code&gt;skip/noskip&lt;/code&gt; block.  The code in this block doesn't affect the transpiled JavaScript, but it keeps any Python linter that you may have in your IDE quiet by stubbing out the JavaScript commands that are otherwise unknown to Python.&lt;/p&gt;

&lt;p&gt;Next, we use the Node &lt;code&gt;require()&lt;/code&gt; function to load the React JavaScript libraries into the module namespace.  Then, we map the React &lt;code&gt;createElement()&lt;/code&gt; and &lt;code&gt;useState()&lt;/code&gt; methods to module-level Python variables as we did before.  As we'll see shortly, this will allow us to import those variables into other Python modules.  Finally, we moved the &lt;code&gt;render()&lt;/code&gt; function we created previously into this module as well.&lt;/p&gt;

&lt;p&gt;Now that we have the JavaScript interface somewhat self-contained, we can utilize it in our application:&lt;/p&gt;

&lt;p&gt;Listing 9: &lt;a href="https://github.com/JennaSys/rtp_demo/blob/main/app.py" rel="noopener noreferrer"&gt;&lt;em&gt;app.py&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pyreact&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;createElement&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ListItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;items&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;li&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;newItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setNewItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;# setItems(items.__add__(newItem))
&lt;/span&gt;        &lt;span class="nf"&gt;setItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;newItem&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# __:opov
&lt;/span&gt;        &lt;span class="nf"&gt;setNewItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;target&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="nf"&gt;setNewItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;form&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;onSubmit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
              &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;label&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;htmlFor&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;newItem&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New Item: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;newItem&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;onChange&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;newItem&lt;/span&gt;
                           &lt;span class="p"&gt;}&lt;/span&gt;
                 &lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;submit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
              &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ol&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;items&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
                 &lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As mentioned before, we import the JavaScript mappings that we need from the &lt;strong&gt;pyreact.py&lt;/strong&gt; module, just like we would any other Python import.  We aliased the React &lt;code&gt;createElement()&lt;/code&gt; method to &lt;code&gt;el&lt;/code&gt; to make it a little easier to work with.&lt;/p&gt;

&lt;p&gt;If you're already familiar with React, you're probably wondering at this point why we're calling &lt;code&gt;createElement()&lt;/code&gt; directly and not hiding those calls behind JSX.  The reason has to do with the fact that Transcrypt utilizes the Python AST module to parse the PY files, and since JSX syntax is not valid Python, it would break that.  There &lt;em&gt;are&lt;/em&gt; ways to utilize JSX with Transcrypt if you really wanted to, but in my opinion the way you have to do it kind of defeats the purpose of using JSX in the first place.&lt;/p&gt;

&lt;p&gt;In this module, we created two functional React components.  The &lt;code&gt;App&lt;/code&gt; component is the main entry point and serves as the top of the component tree that we are building.  Here we have two state variables that we create along with their companion setter functions.  The &lt;code&gt;newItem&lt;/code&gt; state variable will hold an entered value that is to be added to the list.  The &lt;code&gt;items&lt;/code&gt; state variable will then hold all of the values that have been previously entered.&lt;/p&gt;

&lt;p&gt;We then have two functions, one to perform an action when the form submits the value that was entered, and another that synchronizes the value that is being entered with the state of our React component.&lt;/p&gt;

&lt;p&gt;Then, in the return statement of the &lt;code&gt;App()&lt;/code&gt; function, we declare the tree of elements that define the UI.  The top of the element tree starts with an HTML &lt;code&gt;form&lt;/code&gt;.  This allows us to take advantage of its default submit button, which in this case calls our &lt;code&gt;handleSubmit()&lt;/code&gt; function that will add new values to the list.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;handleSubmit()&lt;/code&gt; function, when adding a new item to our list, we used an in-line compiler directive to let Transcrypt know that this particular line of code is using an operator overload:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

        &lt;span class="nf"&gt;setItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;newItem&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# __:opov`  
&lt;/span&gt;&lt;span class="sb"&gt;``&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;span class="n"&gt;By&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Transcrypt&lt;/span&gt; &lt;span class="n"&gt;turns&lt;/span&gt; &lt;span class="n"&gt;off&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;capability&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;would&lt;/span&gt; &lt;span class="n"&gt;cause&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;generated&lt;/span&gt; &lt;span class="n"&gt;JavaScript&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;take&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;performance&lt;/span&gt; &lt;span class="n"&gt;hit&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;were&lt;/span&gt; &lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="n"&gt;globally&lt;/span&gt; &lt;span class="n"&gt;due&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;overhead&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;implement&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;  &lt;span class="n"&gt;If&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;d rather not use the compiler directive to enable operator overloading only where needed, in a case like this you could also call the appropriate Python operator overload dunder method directly as shown in the commented line just above it.

Inside (or below) that, we have an `input` element for entering new values along with a corresponding `label` element that identifies it in the UI.   The `input` element has the `handleChange()` function as its `onChange` event handler that keeps the React state synced up with what the UI is showing.

Next in the element tree is the list of values that have already been entered.  These will be displayed in the UI using an HTML ordered list element that will number the items that are added to it.

This brings us to this module&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="n"&gt;functional&lt;/span&gt; &lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sb"&gt;`ListItems`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;renders&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;our&lt;/span&gt; &lt;span class="sb"&gt;`items`&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;variable&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;HTML&lt;/span&gt; &lt;span class="sb"&gt;`li`&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;  &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="sb"&gt;`items`&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;passed&lt;/span&gt; &lt;span class="n"&gt;into&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;component&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt; &lt;span class="n"&gt;deconstruct&lt;/span&gt; &lt;span class="n"&gt;into&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt; &lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;  &lt;span class="n"&gt;From&lt;/span&gt; &lt;span class="n"&gt;there&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="n"&gt;comprehension&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="sb"&gt;`li`&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;iterating&lt;/span&gt; &lt;span class="n"&gt;through&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;imported&lt;/span&gt; &lt;span class="sb"&gt;`render()`&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;attach&lt;/span&gt; &lt;span class="n"&gt;our&lt;/span&gt; &lt;span class="sb"&gt;`App`&lt;/span&gt; &lt;span class="n"&gt;React&lt;/span&gt; &lt;span class="n"&gt;component&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;DOM&lt;/span&gt; &lt;span class="n"&gt;hook&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="n"&gt;identified&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="sb"&gt;`'root'`&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;HTML&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="sb"&gt;``&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;
&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sb"&gt;``&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;span class="n"&gt;You&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ll notice that because we put all of the Python-to-JavaScript mappings in the **pyreact.py** module, that this module can be 100% pure pythonic Python.  No mixing of languages, no weird contortions of the Python language, and no JavaScript!

To complete this demo, we now just need an HTML entry point that we can load into a web browser:

Listing 10: [*index.html*](https://github.com/JennaSys/rtp_demo/blob/main/index.html)
```html
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;script src=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&amp;lt;/script&amp;gt;
        &amp;lt;title&amp;gt;React to Python&amp;lt;/title&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;div id=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
```

This time, instead of running Transcrypt directly, we can run the `parcel` command using the Node `npx` package runner.  And thanks to the Transcrypt Parcel plugin, it will also run Transcrypt for us and bundle up the generated JavaScript files:  

(venv) $ `npx parcel --log-level 4 --no-cache index.html`  

This also starts up the Parcel development webserver that will serve up the generated content using a default route at:  
http://localhost:1234  

![React App Screenshot](https://github.com/JennaSys/rtp_demo/raw/main/images/app_screenshot.png)

And with this, we have the foundational basis for building React applications using Python!

&amp;amp;nbsp;

## For more...
If you are interested in learning more details about what is presented here, the [React to Python](https://pyreact.com) book dives a lot deeper into what is needed to develop complete web applications using this approach.  

[![Cover image for the React to Python book](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cq6kw5yv5wr7wwdbd7yi.jpg)](https://pyreact.com)

**The book Includes:**
- Setting up the required developer environment tools
- Creating CRUD Forms
- Asynchronous requests with a Flask REST service
- Basics of using the Material-UI component library
- Single Page Applications
- Basic user session management
- SPA view Routing
- Incorporating Google Analytics into your application
- Walks you through building a [complete demo project](https://rtp.jennasys.com)  
[![Screenshot of the project featured in the React to Python book](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y9x5qe830npmt5qdorii.png)](https://rtp.jennasys.com)
&amp;amp;nbsp;

## Resources
- Source Code:
    https://github.com/JennaSys/rtp_demo  

- Transcrypt Site:
    https://www.transcrypt.org  

- Transcrypt GitHub:
    https://github.com/TranscryptOrg/Transcrypt  

- React to Python Book:
    https://pyreact.com  

*This content was originally released as a download on [Leanpub](https://leanpub.com/rtptutorial)*
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>python</category>
      <category>react</category>
      <category>transcrypt</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Python and the Browser - Revisited</title>
      <dc:creator>JennaSys</dc:creator>
      <pubDate>Sat, 10 Apr 2021 01:57:20 +0000</pubDate>
      <link>https://dev.to/jennasys/python-and-the-browser-revisited-52g0</link>
      <guid>https://dev.to/jennasys/python-and-the-browser-revisited-52g0</guid>
      <description>&lt;p&gt;A while back, I posted about my initial foray into using Python to develop front-end web applications with React by using the &lt;a href="https://transcrypt.org" rel="noopener noreferrer"&gt;Transcrypt&lt;/a&gt; transpiler.&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="https://jennasys.medium.com/python-and-the-browser-4d0fa659722d" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A88%3A88%2F2%2A02fzlJzu8xK_fWC7GrDnEg.jpeg" alt="JennaSys"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://jennasys.medium.com/python-and-the-browser-4d0fa659722d" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Python and the Browser. I had to find out: Was it actually… | by JennaSys | Medium&lt;/h2&gt;
      &lt;h3&gt;JennaSys ・ &lt;time&gt;Mar 6, 2022&lt;/time&gt; ・ 
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fmedium-f709f79cf29704f9f4c2a83f950b2964e95007a3e311b77f686915c71574fef2.svg" alt="Medium Logo"&gt;
        jennasys.Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;&lt;br&gt;
Part of the initial learning process I went through was doing the official &lt;a href="https://reactjs.org/tutorial/tutorial.html" rel="noopener noreferrer"&gt;React tutorial&lt;/a&gt;, but using Python for the code instead of JavaScript.  When I did that, I adhered to the  structure of the application that was used in the tutorial pretty closely.  Since then, I have been working with Transcrypt and React quite a bit more and have formed some of my own standards of practice for producing clean Python code in my React applications.  In this post, I'll show you a few of those practices as I take the original class-based version of that program I did (which is what the React tutorial is based on), and convert it to use functional components and React hooks instead (which is all I use now).
&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;The premise of the React tutorial is a &lt;em&gt;Tic-Tac-Toe&lt;/em&gt; game that maintains a history of moves, where you can reset the board back to any previous point.  The design consists of a Game component that manages the state of the game and holds the history of moves.  Then there is a Board component that handles the rendering of the board.  And Lastly, there is a Square component that renders a single square in the game.&lt;/p&gt;

&lt;p&gt;My &lt;a href="https://github.com/JennaSys/tictacreact" rel="noopener noreferrer"&gt;original version&lt;/a&gt; of the application has four files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;index.html&lt;/strong&gt;  (the application entry point and DOM root)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;game.css&lt;/strong&gt;  (CSS selectors for the application)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tictacreact.py&lt;/strong&gt;  (the application code in Python)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pyreact.py&lt;/strong&gt;  (Python wrappers for the React.Component class and miscellaneous JavaScript functions)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Support Files
&lt;/h3&gt;

&lt;p&gt;For this makeover, the CSS file and the &lt;strong&gt;index.html&lt;/strong&gt; file will remain pretty much unchanged:&lt;/p&gt;

&lt;p&gt;Listing 1: &lt;a href="https://github.com/JennaSys/tictacreact2/blob/master/index.html" rel="noopener noreferrer"&gt;&lt;em&gt;index.html&lt;/em&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Tic Tac React!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"shortcut icon"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"favicon.ico"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/x-icon"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;crossorigin&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/react@16/umd/react.production.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;crossorigin&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"game.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"__target__/tictacreact.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we will no longer be using React class components, we can clean up the &lt;strong&gt;pyreact.py&lt;/strong&gt; file quite a bit.  I use this Python module to hold all of the Python-to-JavaScript mappings, that I can then import into other Python modules.  This approach facilitates keeping any JavaScript messiness in one place and allows all of the other Python modules to remain pure Python, which keeps the Python linter happy.&lt;/p&gt;

&lt;p&gt;For most projects, I've been using the Parcel bundler which has a &lt;a href="https://www.npmjs.com/package/parcel-plugin-transcrypt" rel="noopener noreferrer"&gt;Transcrypt plug-in&lt;/a&gt; available for it.  With that, I would normally have a few lines in the &lt;strong&gt;pyreact.py&lt;/strong&gt; module to load the React libraries with a JavaScript ES5 style import that uses the Node &lt;code&gt;require()&lt;/code&gt; function like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;React&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;react&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ReactDOM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;react-dom&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, since we are loading the React libraries in the HTML header, the React and ReactDOM namespaces will be global, so I instead just stubbed out those libraries in the Python file.&lt;/p&gt;

&lt;p&gt;Listing 2: &lt;a href="https://github.com/JennaSys/tictacreact2/blob/master/pyreact.py" rel="noopener noreferrer"&gt;&lt;em&gt;pyreact.py&lt;/em&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# __pragma__ ('skip')
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
These JavaScript object stubs are just to
quiet the Python linter and are ignored by transcrypt as long
as they are imported inside of pragma skip/noskip lines.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;createElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;useState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;useEffect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;createContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;useContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;document&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;getElementById&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;addEventListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="c1"&gt;# __pragma__ ('noskip')
&lt;/span&gt;

&lt;span class="c1"&gt;# Map React javaScript objects to Python identifiers
&lt;/span&gt;&lt;span class="n"&gt;createElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createElement&lt;/span&gt;
&lt;span class="n"&gt;useState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;useState&lt;/span&gt;
&lt;span class="n"&gt;useEffect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;useEffect&lt;/span&gt;
&lt;span class="n"&gt;createContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createContext&lt;/span&gt;
&lt;span class="n"&gt;useContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;useContext&lt;/span&gt;


&lt;span class="c1"&gt;# Wrap the ReactDOM.render method to hide JavaScript details
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root_component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root_component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The section between the skip/noskip &lt;code&gt;pragma&lt;/code&gt; lines isn't really needed other than to quiet the Python linter not being able to resolve the JavaScript object names.  They are just Python stub declarations that will ultimately be ignored by Transcrypt thanks to the compiler directives.&lt;/p&gt;

&lt;p&gt;The mappings in this file are where Transcrypt does a lot of its magic.  I'm basically assigning a JavaScript object to a Python variable.  From there, it can be used just like any other Python object.  It can be imported into other Python modules, and its methods can be called.  Even though I'm using JavaScript libraries, I only need to know the library's API to code to it using Python.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;render()&lt;/code&gt; function doesn't change from before, and is just a wrapper around the &lt;code&gt;ReactDOM.render()&lt;/code&gt; method that lets us encapsulate the JavaScript calls that go along with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Refactoring
&lt;/h3&gt;

&lt;p&gt;Most of the actual refactoring we did in this version of the application was in the &lt;strong&gt;tictacreact.py&lt;/strong&gt; module.  Beyond just turning the class components into functional components, we also changed how some of the state gets updated.  While it didn't save us many lines of code, it is now a bit more modularized and (hopefully) more readable than what was there before.&lt;/p&gt;

&lt;p&gt;Listing 3: &lt;a href="https://github.com/JennaSys/tictacreact2/blob/master/tictacreact.py" rel="noopener noreferrer"&gt;&lt;em&gt;tictacreact.py&lt;/em&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pyreact&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;createElement&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pyreact&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;useContext&lt;/span&gt;


&lt;span class="n"&gt;Ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;Square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;idx&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;squares&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;button&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;className&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;square&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                         &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;squares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;rowNum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rowNum&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Square&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;idx&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rowNum&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;col_num&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;col_num&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;className&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;board-row&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;Board&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rowNum&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row_num&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row_num&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;Moves&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;numMoves&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;numMoves&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;setStepNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;setStepNumber&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Go to move #&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Go to game start&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;li&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;button&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;className&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;move-history&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;setStepNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;desc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                  &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;get_move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numMoves&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setHistory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)]}])&lt;/span&gt;
    &lt;span class="n"&gt;stepNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setStepNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;board&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stepNumber&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;xIsNext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stepNumber&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;winner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_winner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;winner&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Winner: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;winner&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;stepNumber&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No Winner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Next player: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;X&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;xIsNext&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;O&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;new_squares&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;winner&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;new_squares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="c1"&gt;# Already winner or square not empty
&lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="c1"&gt;# Nothing to do
&lt;/span&gt;
        &lt;span class="n"&gt;new_squares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;X&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;xIsNext&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;O&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

        &lt;span class="n"&gt;tmp_history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;stepNumber&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# Slice in case step changed
&lt;/span&gt;        &lt;span class="n"&gt;new_history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tmp_history&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;new_history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;new_squares&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="nf"&gt;setHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;setStepNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                                       &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;handle_click&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                             &lt;span class="p"&gt;},&lt;/span&gt;
              &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;className&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;game&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                 &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;className&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;game-board&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Board&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;className&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;game-status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="p"&gt;),&lt;/span&gt;
                 &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;className&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;game-info&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Move History&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ol&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Moves&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;numMoves&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                  &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;setStepNumber&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;setStepNumber&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                          &lt;span class="p"&gt;)&lt;/span&gt;
                       &lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;
                 &lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# Render the component in a 'container' div
&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_winner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;squares&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;squares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;squares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;squares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;squares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;squares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;squares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the main &lt;code&gt;Game&lt;/code&gt; component, we made several changes starting with converting the class-based &lt;code&gt;state&lt;/code&gt; object to individual &lt;code&gt;useState()&lt;/code&gt; hooks instead.  So the &lt;code&gt;history&lt;/code&gt; and &lt;code&gt;stepNumber&lt;/code&gt; state variables now have their own companion update functions. &lt;/p&gt;

&lt;p&gt;Since the &lt;code&gt;xIsNext&lt;/code&gt; state variable that was being used before is just calculated based on the value of another state variable, I changed it to be a local variable instead.  It will get recalculated if a re-render happens due to a change in the state that it is based on. &lt;/p&gt;

&lt;p&gt;To clarify what is being displayed at any given time, I also added the local variable &lt;code&gt;board&lt;/code&gt; to hold the current board values as a convenience.   Now, as determined by the &lt;code&gt;stepNumber&lt;/code&gt;, we pull it out of the history list just once instead of every time we need to use it as we were doing before.   This value also gets recalculated when a re-render happens. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;handle_click()&lt;/code&gt; function gets cleaned up a little, but it is still a bit busy since we need to make copies of the &lt;code&gt;history&lt;/code&gt; and &lt;code&gt;board&lt;/code&gt; squares in order to update them since we are working with immutable objects.  Until Transcrypt adds the Python &lt;code&gt;copy&lt;/code&gt; standard library to what it supports, you either have to use a JavaScript function to do that, or do it manually as we did here for &lt;code&gt;history&lt;/code&gt; where we used a list comprehension:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;new_history&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt;  &lt;span class="n"&gt;move&lt;/span&gt;  &lt;span class="ow"&gt;in&lt;/span&gt;  &lt;span class="n"&gt;tmp_history&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the list of previous moves that get displayed in the UI, instead of generating the list item elements in the &lt;code&gt;Game&lt;/code&gt; component, we moved that functionality into its own &lt;code&gt;Moves&lt;/code&gt; component.  This change cleans up the &lt;code&gt;Game&lt;/code&gt; component and makes the overall application structure a little more readable.&lt;/p&gt;

&lt;p&gt;One of the practices I started doing was to deconstruct the values held in the &lt;code&gt;props&lt;/code&gt; object into local variables rather than directly referencing them from &lt;code&gt;props&lt;/code&gt; just when they are needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;Moves&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;numMoves&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;numMoves&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;setStepNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;setStepNumber&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This practice accomplishes two things.  First, by deconstructing all of the values right at the top of the function definition, I know exactly what props that component is expecting without having to search the entire function to figure it out.  Second, it cleans up the code in the function where I actually use those values by not having to do the dictionary lookups in place.&lt;/p&gt;

&lt;p&gt;The last somewhat subtle change we made is to put the &lt;code&gt;handle_click()&lt;/code&gt; function and the &lt;code&gt;board&lt;/code&gt; squares into a context variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;handle_click&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                            &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this context variable saves us from having to pass these values down through several other layers of components that don't need them, just so that we can use them in the &lt;code&gt;Square&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Board&lt;/code&gt; component, we really cleaned it up in that it now just returns a &lt;code&gt;div&lt;/code&gt; element with three &lt;code&gt;Row&lt;/code&gt; components.  And since we are now using the context variable, we no longer need to pass any props into it.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Row&lt;/code&gt; component is something new we added with this refactor that clarifies conceptually what is being generated.  Similar to the &lt;code&gt;Board&lt;/code&gt; component, the &lt;code&gt;Row&lt;/code&gt; component returns a &lt;code&gt;div&lt;/code&gt; element containing just three &lt;code&gt;Square&lt;/code&gt; components.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Square&lt;/code&gt; component is now a bonafide React component instead of just an imperative function.  Functionally it is the same as before, but we did add in the React &lt;code&gt;useContext()&lt;/code&gt; hook to pull out the values we needed to use here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;squares&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;squares&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;onClick&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we just made some minor optimizations to the &lt;code&gt;calculate_winner()&lt;/code&gt; function from the earlier version. &lt;/p&gt;

&lt;h3&gt;
  
  
  Transpile &amp;amp; Run
&lt;/h3&gt;

&lt;p&gt;Right now, Transcrypt version 3.7.16 only works with Python 3.6 or 3.7, so in setting up a virtual environment, I'll use this:  &lt;/p&gt;

&lt;p&gt;$ &lt;code&gt;python3.7 -m venv venv&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;then activate it:  &lt;/p&gt;

&lt;p&gt;$ &lt;code&gt;source ./venv/bin/activate&lt;/code&gt;&lt;br&gt;&lt;br&gt;
(for Windows use   &lt;code&gt;venv\Scripts\activate&lt;/code&gt; )  &lt;/p&gt;

&lt;p&gt;and then install Transcrypt:  &lt;/p&gt;

&lt;p&gt;(venv) $ &lt;code&gt;pip install transcrypt&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;To build the application, you just need to give Transcrypt the entry point of your application, and it will walk the dependency tree to transpile any other related modules:  &lt;/p&gt;

&lt;p&gt;(venv) $ &lt;code&gt;transcrypt --nomin --build --map tictacreact&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We also gave it a few CLI options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;nomin&lt;/em&gt; - tells it not to minify the generated JavaScript (Note: The Java runtime is needed for this to work)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;build&lt;/em&gt; - tells it to start from scratch&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;map&lt;/em&gt; - tells it to generate a JavaScript-to-Python source code map file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once that is done, we need to serve up the generated files before we can open up the application in a web browser.  A quick way to do this is using the HTTP server that comes with Python:&lt;/p&gt;

&lt;p&gt;(venv) $ &lt;code&gt;python -m http.server&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;Then open the application:&lt;br&gt;&lt;br&gt;
&lt;a href="http://localhost:8000/index.html" rel="noopener noreferrer"&gt;http://localhost:8000/index.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqzas7d5ktnr1bw1p507f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqzas7d5ktnr1bw1p507f.png" alt="Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find all of the source code for this application here:&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/JennaSys/tictacreact2" rel="noopener noreferrer"&gt;https://github.com/JennaSys/tictacreact2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A live demo of this code (with source maps)  is also hosted on GitHub Pages:&lt;br&gt;&lt;br&gt;
&lt;a href="https://jennasys.github.io/tictacreact2/" rel="noopener noreferrer"&gt;https://jennasys.github.io/tictacreact2/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;As someone that really likes Python and isn't a big fan of JavaScript, using Transcrypt to develop React applications with Python has been working out decidedly well for me so far.  To share how I was doing it, I had started putting together an outline for a talk I was going to give at my Python meetup group.  As it turned out, that outline kept growing, and I ended up writing an entire book about it instead.  If you're interested, you can find out more about the "React to Python" book here:  &lt;a href="https://pyreact.com" rel="noopener noreferrer"&gt;https://pyreact.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>react</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
