{"id":13445610,"url":"https://github.com/ryansolid/mobx-jsx","last_synced_at":"2025-04-05T23:05:25.707Z","repository":{"id":40380469,"uuid":"142264104","full_name":"ryansolid/mobx-jsx","owner":"ryansolid","description":"Raw MobX performance without being restrained by a Virtual DOM","archived":false,"fork":false,"pushed_at":"2023-01-09T09:43:03.000Z","size":390,"stargazers_count":262,"open_issues_count":8,"forks_count":10,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-29T22:07:40.811Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ryansolid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-25T07:30:47.000Z","updated_at":"2025-03-23T05:00:29.000Z","dependencies_parsed_at":"2023-02-08T09:45:33.374Z","dependency_job_id":null,"html_url":"https://github.com/ryansolid/mobx-jsx","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryansolid%2Fmobx-jsx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryansolid%2Fmobx-jsx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryansolid%2Fmobx-jsx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryansolid%2Fmobx-jsx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ryansolid","download_url":"https://codeload.github.com/ryansolid/mobx-jsx/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247411226,"owners_count":20934653,"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-31T05:00:36.539Z","updated_at":"2025-04-05T23:05:25.690Z","avatar_url":"https://github.com/ryansolid.png","language":"TypeScript","funding_links":[],"categories":["Integrations"],"sub_categories":["Other JSX based libraries"],"readme":"# MobX JSX\r\n\r\nThis library is a demonstration of how MobX fine grain control can be leveraged directly in JSX for considerably better performance than pairing it with a Virtual DOM library. Even the fastest Virtual DOM library will have overhead when reconciling many small discrete changes into a scheduled render and patch.\r\n\r\nCheck out MobX JSX performance near the top of the charts on the [JS Frameworks Benchmark](https://github.com/krausest/js-framework-benchmark).\r\n\r\nIt accomplishes this with using [Babel Plugin JSX DOM Expressions](https://github.com/ryansolid/dom-expressions/tree/master/packages/babel-plugin-jsx-dom-expressions). It compiles JSX to DOM statements and wraps expressions in functions that can be called by the library of choice. In this case `autorun` wraps these expressions ensuring the view stays up to date. Unlike Virtual DOM only the changed nodes are affected and the whole tree is not re-rendered over and over.\r\n\r\n## Usage\r\n\r\nTo use call render as follow\r\n\r\n```js\r\nimport { render } from \"mobx-jsx\";\r\n\r\nrender(App, document.getElementById(\"main\"));\r\n```\r\n\r\nAnd include 'babel-plugin-jsx-dom-expressions' in your babelrc, webpack babel loader, or rollup babel plugin.\r\n\r\n```js\r\n\"plugins\": [[\"babel-plugin-jsx-dom-expressions\", {moduleName: 'mobx-jsx'}]]\r\n```\r\n\r\nSee [plugin options](https://github.com/ryansolid/dom-expressions/tree/master/packages/babel-plugin-jsx-dom-expressions#plugin-options)\r\n\r\nFor TS JSX types add to your `tsconfig.json`:\r\n\r\n```js\r\n\"jsx\": \"preserve\",\r\n\"jsxImportSource\": \"mobx-jsx\"\r\n```\r\n\r\n## Installation\r\n\r\n```sh\r\n\u003e npm install mobx-jsx babel-plugin-jsx-dom-expressions\r\n```\r\n\r\n## Examples\r\n\r\n- [Counter Using Functions](https://codesandbox.io/s/mobx-counterfunctions-3sqv1)\r\n- [Counter Using Classes](https://codesandbox.io/s/mobx-counterclasses-uz7g9)\r\n- [Lazy Loading](https://codesandbox.io/s/mobx-lazy-demo-ev95s)\r\n- [Context](https://codesandbox.io/s/mobx-counter-context-wlu1x)\r\n\r\n## API\r\n\r\nMobX JSX works both with function and Class components (extend Component from this library).\r\n\r\n### Map For Observable Arrays\r\n\r\nShips a specialize map function for optimal list rendering that takes an observable array as it's first argument. To avoid re-rendering the complete list on changes.\r\n\r\n```jsx\r\nimport { map } from \"mobx-jsx\";\r\n\r\nconst list = observable([\"Alpha\", \"Beta\", \"Gamma\"]);\r\n\r\n\u003cul\u003e\r\n  {map(list, item =\u003e (\r\n    \u003cli\u003e{item}\u003c/li\u003e\r\n  ))}\r\n\u003c/ul\u003e;\r\n```\r\n\r\n### Lifecycles\r\n\r\nUnlike React `render` only runs once, so you may not need to split in functions or methods your Lifecycles, all the initialization code could be set on `render`. See the issue [Lifecycles](https://github.com/ryansolid/mobx-jsx/issues/23) for further information.\r\n\r\nHowever, you may emulate `componentDidMount` and `componentWillUnmount`. The microtask `Promise` resolution will be after mount and `cleanup` runs at the beginning of re-evaluation so the elements aren't removed yet.\r\n\r\n#### Example\r\n\r\n```jsx\r\nimport { render, cleanup, Component as _Component } from \"mobx-jsx\";\r\n\r\nclass Component extends _Component {\r\n  constructor(props) {\r\n    super(props);\r\n    if (this.componentDidMount) {\r\n      Promise.resolve().then(() =\u003e this.componentDidMount());\r\n    }\r\n    if (this.componentWillUnmount) {\r\n      cleanup(() =\u003e this.componentWillUnmount());\r\n    }\r\n  }\r\n}\r\n\r\nclass App extends Component {\r\n  componentDidMount() {\r\n    console.log(\"componentDidMount\");\r\n  }\r\n  componentWillUnmount() {\r\n    console.log(\"componentWillUnmount\");\r\n  }\r\n}\r\n```\r\n\r\n### Mounting\r\n\r\nMounting can be done by functions and not class components. However you may use an arrow function as follows:\r\n\r\n```jsx\r\nimport { render, Component } from \"mobx-jsx\";\r\n\r\nclass App extends Component {\r\n  render() {\r\n    return \u003cdiv\u003eMounted\u003c/div\u003e\r\n  }\r\n}\r\n\r\nrender(() =\u003e \u003cApp /\u003e, document.body);\r\n```\r\n\r\n### References\r\n\r\n`ref` assigns to a variable. \r\n\r\n\r\n```jsx\r\nlet elRef;\r\nPromise.resolve().then(() =\u003e elRef.clientWidth);\r\n\u003cdiv ref={elRef} /\u003e\r\n```\r\n\r\nNote: Promise.resolve().then is used as `mount` see the issue [Lifecycles](https://github.com/ryansolid/mobx-jsx/issues/23) for further information.\r\n\r\n### Lazily Loading a Component\r\n\r\n```jsx\r\nimport { render, lazy } from \"mobx-jsx\";\r\n\r\n// use lazy to allow code splitting\r\nconst SomeComponent = lazy(() =\u003e import(\"./SomeComponent\"));\r\n\r\nfunction App() {\r\n  return (\r\n    \u003c\u003e\r\n      \u003cSomeComponent name={\"John\"} /\u003e\r\n    \u003c/\u003e\r\n  );\r\n}\r\n\r\nrender(App, document.body);\r\n```\r\n\r\n### MobX JSX also supports a Context API.\r\n\r\n## Non-precompiled environments\r\n\r\nAlternatively supports Tagged Template Literals or HyperScript for non-precompiled environments by installing the companion library and including variants:\r\n\r\n```js\r\nimport { html } from \"mobx-jsx/html\"; // or\r\nimport { h } from \"mobx-jsx/h\";\r\n```\r\n\r\nThere is a small performance overhead of using these runtimes but the performance is still very impressive. Tagged Template solution is much more performant that the HyperScript version, but HyperScript opens up compatibility with some companion tooling like:\r\n\r\n- [HyperScript Helpers](https://github.com/ohanhi/hyperscript-helpers) Use an element as functions DSL\r\n- [Babel Plugin HTM](https://github.com/developit/htm/tree/master/packages/babel-plugin-htm) Transpile Tagged Template Literals to HyperScript for IE11 compatibility\r\n\r\nFurther documentation available at: [Lit DOM Expressions](https://github.com/ryansolid/lit-dom-expressions) and [Hyper DOM Expressions](https://github.com/ryansolid/hyper-dom-expressions).\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryansolid%2Fmobx-jsx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fryansolid%2Fmobx-jsx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryansolid%2Fmobx-jsx/lists"}