{"id":13442564,"url":"https://github.com/nilesr/jscl-react","last_synced_at":"2026-01-27T22:41:45.388Z","repository":{"id":70532566,"uuid":"262660647","full_name":"nilesr/jscl-react","owner":"nilesr","description":"A web framework for writing react components in common lisp using jscl","archived":false,"fork":false,"pushed_at":"2020-05-13T05:46:52.000Z","size":11407,"stargazers_count":17,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-28T05:59:21.960Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nilesr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-05-09T21:18:10.000Z","updated_at":"2022-05-28T11:56:30.000Z","dependencies_parsed_at":"2023-02-25T16:00:37.628Z","dependency_job_id":null,"html_url":"https://github.com/nilesr/jscl-react","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilesr%2Fjscl-react","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilesr%2Fjscl-react/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilesr%2Fjscl-react/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilesr%2Fjscl-react/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nilesr","download_url":"https://codeload.github.com/nilesr/jscl-react/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244630176,"owners_count":20484328,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T03:01:47.320Z","updated_at":"2026-01-27T22:41:45.345Z","avatar_url":"https://github.com/nilesr.png","language":"Common Lisp","readme":"## `jscl-react` is a library for writing React components in common lisp, using `jscl`\n\nHere's a quick demo:\n\n![](ss/out.gif)\n\nThe demo application is available to try out [here](https://niles.xyz/jscl-react-demo)\n\n### Reference app demos\n\nI've recreated two of the official React example applications in `jscl-react` to show it off\n\n#### Emoji Search\n\nOriginal project: [ahfarmer/emoji-search](https://github.com/ahfarmer/emoji-search), running live [here](https://ahfarmer.github.io/emoji-search)\n\n`jscl-react` version running [here](https://niles.xyz/jscl-react-demo/emoji-search), source code in the [`emoji-search` subdirectory](https://github.com/nilesr/jscl-react/tree/master/emoji-search)\n\nThe 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`](https://github.com/nilesr/jscl-react/blob/master/emoji-search/filter-emoji.lisp#L1-L8). 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`.\n\n#### Counter App\n\nOriginal project: [arnab-datta/counter-app](https://github.com/arnab-datta/counter-app/), running live [here](https://obscure-waters-60500.herokuapp.com/)\n\n`jscl-react` version running [here](https://niles.xyz/jscl-react-demo/counter-app), source code in the [`counter-app` subdirectory](https://github.com/nilesr/jscl-react/tree/master/counter-app)\n\n### Creating React elements\n\nThe shortcut `react-create-element` is provided for the JavaScript function `React.createElement`. For example:\n\n```\n(react-create-element\n\t\"div\"\n\t#()\n\t(react-create-element \"h1\" #() \"I'm big!\")\n\t\"I'm a text node!\"\n\t(react-create-element \"br\")\n\t(react-create-element \"button\" (object \"onClick\" #j:window:alert) \"Click me!\"))\n```\n\nThe macro `render` is provided to recurse on child elements, where appropriate. The above call can be rewritten as:\n\n```\n(render\n\t\"div\"\n\t#()\n\t(\"h1\" #() \"I'm big!\")\n\t\"I'm a text node!\"\n\t(\"br\")\n\t(\"button\" (object \"onClick\" #j:window:alert) \"Click me!\"))\n```\n\n### Mounting React elements\n\nGiven a mount element like a div with an id, you can place a react element in it like so\n\n```\n(mount \"the-id\" (react-create-element \"h1\" #() \"Hello, world!\"))\n```\n\nDefining a component is as simple as this:\n\n```\n(defcomponent (btn 0) (set-state state props)\n  (let ((handler (lambda (event)\n                   (funcall set-state (1+ state)))))\n    (render\n      \"button\"\n      (object \"onClick\" handler)\n      \"Hello, world: \"\n      state)))\n```\n\nHere, `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`.\n\nThis 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\n\nThe 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\n\n```\n(mount \"root\" (render\n\t\"div\"\n\t#()\n\t(\"h3\" #() \"Here is my cool button:\")\n\t((btn))\n\t\"Isn't it pretty?\"))\n```\n\nProperties should be passed in the way `React.createElement` expects them, like so\n\n```\n(mount \"root\" (render\n\t\"div\"\n\t#()\n\t(\"h3\" #() \"Here is my cool button:\")\n\t((btn) (object \"id\" \"the-button\" \"className\" \"pretty-button\"))\n\t\"Isn't it pretty?\"))\n```\n\n","funding_links":[],"categories":["Common Lisp","Interfaces to other package managers"],"sub_categories":["Isomorphic web frameworks"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnilesr%2Fjscl-react","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnilesr%2Fjscl-react","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnilesr%2Fjscl-react/lists"}