Here's a quick demo:
The demo application is available to try out here
I've recreated two of the official React example applications in jscl-react to show it off
Original project: ahfarmer/emoji-search, running live here
jscl-react version running here, source code in the emoji-search subdirectory
The original project uses import on a json file to make the contents of that file available at runtime, embedded in the code via Babel. I do the same, by loading cl-json at compile time using quicklisp, and storing the parsed contents of the json file in a variable that is then available at runtime. You can see exactly how I did this in emoji-search/filter-emoji.lisp. Alternative ways to do it could have included loading it into a variable as a string and using the browser's JSON.parse at runtime, which would have eliminated the need for quicklisp, or fetching it at runtime using the browser's built-in fetch or XMLHttpRequest.
Original project: arnab-datta/counter-app, running live here
jscl-react version running here, source code in the counter-app subdirectory
The shortcut react-create-element is provided for the JavaScript function React.createElement. For example:
(react-create-element
"div"
#()
(react-create-element "h1" #() "I'm big!")
"I'm a text node!"
(react-create-element "br")
(react-create-element "button" (object "onClick" #j:window:alert) "Click me!"))
The macro render is provided to recurse on child elements, where appropriate. The above call can be rewritten as:
(render
"div"
#()
("h1" #() "I'm big!")
"I'm a text node!"
("br")
("button" (object "onClick" #j:window:alert) "Click me!"))
Given a mount element like a div with an id, you can place a react element in it like so
(mount "the-id" (react-create-element "h1" #() "Hello, world!"))
Defining a component is as simple as this:
(defcomponent (btn 0) (set-state state props)
(let ((handler (lambda (event)
(funcall set-state (1+ state)))))
(render
"button"
(object "onClick" handler)
"Hello, world: "
state)))
Here, btn is the name of the component, and 0 is the initial state. The rest of the definition is the render function for the component, accepting set-state (the function called to update the state), state, and props.
This component's state is a single number. Clicking the returned button increments the state by 1, which is reflected in the text of the button
The name of the component should be invoked to create one, which can then be passed to create-react-element or render. So we can render a btn to the screen like so
(mount "root" (render
"div"
#()
("h3" #() "Here is my cool button:")
((btn))
"Isn't it pretty?"))
Properties should be passed in the way React.createElement expects them, like so
(mount "root" (render
"div"
#()
("h3" #() "Here is my cool button:")
((btn) (object "id" "the-button" "className" "pretty-button"))
"Isn't it pretty?"))
