onClick with React
I'm trying to get some buttons (and eventually other things) with React in Transcrypt.
Unfortunately, I'm getting nowhere and finding no examples besides pyreact which as you can see uses __pragma__
Is that the only way? If so, I'd rather not use React....
Let me more clear on what I am trying to accomplish, my background and how I "solved" it for now, in the hope it may help others who find this issue (if you deem it appropriate, I'd be happy to adapt this as a PR as an alternative method for the React example in transcrypt)
-
I know almost nothing about javascript and React, or babel and transpiling. In fact this is the reason why I am loving transcrypt!!! ;-)) -- in fact the only things I know on React I've learned in the tutorial and demos at https://reactjs.org/tutorial/tutorial.html and https://reactjs.org/docs/hello-world.html and https://github.com/ruanyf/react-demos
-
I am writing the logic of my app in python/transcript and that is going great (in fact I had quite a good headstart, thanks for such a nice tool!!!) -- now I would like to write the UI of such app in React, because that seem more sensible (and probably easier) than trying to do it in plain HTML (like I've done so far for proof of concept)
-
However I am having troubles putting together Transcrypt and React. Looking at Transcrypt's demo for React I am getting stuck in things as "how do I put onClick in there???" (the question in my previous comment)
-
Alternatively, I am trying to use React "standalone" and merge it with Transcrypt with
__pragma__('js', '{}', __include__("hello_react.js"))in python whilehello_react.jsis
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
That would be ideal, but it does not work (it says that < of <h1>Hello, world!</h1> is invalid syntax). I guess my problem is that I know nothing about babel let alone how to integrate it in React or transpile it. Examplese such as these use babel in the browser, but that does not work in Transcrypt (I guess because the script type tag needs to be text/babel for JSX to work in the browser, but instead such type tag is module for things loaded via Transcrypt).
- The second best thing is to use React without JSX so I changed
hello_react.jsto
class Hello extends React.Component {
render() {
return React.createElement('div', null, `Hello ${this.props.toWhat}`);
}
}
ReactDOM.render(
React.createElement(Hello, {toWhat: 'World'}, null),
document.getElementById('root')
);
which finally works.
In conclusion, this may be closed unless
-
you have some advice to give me for doing things better, such as
- how to make 4) work in Transcrypt (either or both with babel in the browser or transpiling JSX to plain javascript for a Transcrypt project), or
- where to find documentation about the approach of 3) which being a hybrid of Python, Transcrypt and React I found not immediate to use
-
if you want me to make a PR demonstrating bullet point 5) above as an alternative method for the React example in transcrypt
@davidedelvento I've been going through the same scenario as you. I started with the Transcrypt React demo and have been expanding it from there.
I'm not using JSX for 2 reasons:
- I didn't want to have to use an external compiler other than Transcrypt
- The code I write is all Python and stays clean
To make things easier, I added a convenience method to pyreact.py that just takes a component and returns a React element (it's the same method included in the pyreact Component class - I just made it a global):
def element(elem, props, *children):
return React.createElement(elem, props, *children)
For readability, I import it into my modules using:
from pyreact import element as el
then use it something like this:
el('div', None, "Hello World"))
Finally, to include React as a built in module rather than as a global, try saving this in a module like react_libs.py:
from org.transcrypt.stubs.browser import __pragma__
from org.transcrypt.stubs.browser import __include__
__pragma__('noanno')
# returns React object
React = __pragma__('js',
'''
(function () {{
var exports = {{}};
{} // Puts react in exports and in global window
return window.React;
}}) ();
''',
__include__('./node_modules/react/umd/react.development.js')
)
# returns ReactDOM object
ReactDOM = __pragma__('js',
'''
(function () {{
var exports = {{}};
{} // Puts react in exports and in global window
var tmp_lib = window.ReactDOM;
delete window.React.React;
delete window.ReactDOM;
return tmp_lib;
}}) ();
''',
__include__('./node_modules/react-dom/umd/react-dom.development.js')
)
You can then use React and ReactDOM as valid Python objects from other modules:
from react_libs.py import React, ReactDOM
By deleting them from the window object after saving a reference, the React libs don't pollute the global namespace in the browser. Disclaimer: I had help figuring out the syntax for the lib module above.
Using Transcrypt to create React/MaterialUI apps from Python has been working out really well for me despite having to find patterns for the language translations. In case it helps, here is my repo for the React tutorial code And here is the live app with non-minified js and sourcemap to the python code.
As a follow-up, I started using parcel-builder and I now just do this to import JS modules:
React = require('react')
ReactDOM = require('react-dom')
If the JS module exports a default, the import might need to look like this:
NumberFormat = require('react-number-format')['default']
And to keep build time low and not import entire libraries, you can drill down into the library and do this to just import what you need out of them:
MenuIcon = require('@material-ui/icons/Menu')['default']
Lastly, in some cases using the libraries requires a syntax change. For example, with Axios you would normally do this:
import axios from 'axios';
axios.get('/api/stuff')
But in Python, I do this:
axios = require('axios')
axios['get']('/api/stuff')
If you want the syntax to use the dot like in JS, you can wrap the JS lib in a class:
# __pragma__ ('kwargs')
class Axios:
@staticmethod
def get(url, **kwargs):
return axios['get'](url, **kwargs)
# __pragma__ ('nokwargs')
The you can use it as Axios.get('/api/stuff')
In case anyone else is trying to use JSX in React with Transcrypt, it took me a while to figure out how to make it work so I'll leave this here in case it will save someone else some time.
When using the xtrans pragma, I believe the JSX needs to either be a string literal or brought in from another file using __include__, which IMO is cleaner and more maintainable than putting all the JSX into a string. So for example, if you put all of your JSX code into a file called test.jsx:
<div>
<button onClick={hello}>Click Me</button>
</div>
You could then use this:
def hello():
alert("Hello World!")
__pragma__('xtrans', 'jsx-transform --factory createElement', '{}', __include__('./test.jsx'))
Also don't forget to make sure that jsx-transform-cli is installed in your project so it actually transpiles the JSX.
npm install --save-dev jsx-transform-cli
I can not seem to get the above to work on Windows. If I manually convert the jsx file from the command line:
type app.jsx | jsx-transform --factory createElement > app.js
and then use a __pragma__('js') with the transpiled js file it works:
__pragma__('js', '{}', __include__('app.js'))
The jsx-transform-cli package seems to be installed correctly, and I haven't noticed any errors in the build output. Is there anything I can check? Has anyone else tried this on Windows?
Update: It looks like there may have been a prior fix for this but may have been lost during a merge with branch old_master. The xtrans command line argument was removed at the same time.

With no further comments for a while now, I'll close this out. But for anyone that stumbles upon this and wants to know how to effectively create React applications in Python, I've written up a few of the ways that I approach it:
- Creating React Applications with Python
- Eliminate explicit calls to createElement() when using Python to code React applications
- Using Parcel v2 and Transcrypt to create web applications with Python
I also made a version of the official React tutorial application written in Python that you can use as some example code.