{"id":20819587,"url":"https://github.com/calmm-js/karet","last_synced_at":"2025-05-07T15:23:23.180Z","repository":{"id":47426869,"uuid":"69846767","full_name":"calmm-js/karet","owner":"calmm-js","description":"Karet is a library that allows you to embed Kefir observables into React VDOM","archived":false,"fork":false,"pushed_at":"2021-08-31T23:49:59.000Z","size":482,"stargazers_count":86,"open_issues_count":9,"forks_count":8,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-22T13:55:21.328Z","etag":null,"topics":["counterculture","incremental","jsx","kefir","observables","react","reactive","vdom"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/calmm-js.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-10-03T06:40:18.000Z","updated_at":"2025-03-11T14:19:05.000Z","dependencies_parsed_at":"2022-07-25T01:16:53.929Z","dependency_job_id":null,"html_url":"https://github.com/calmm-js/karet","commit_stats":null,"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/calmm-js%2Fkaret","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/calmm-js%2Fkaret/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/calmm-js%2Fkaret/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/calmm-js%2Fkaret/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/calmm-js","download_url":"https://codeload.github.com/calmm-js/karet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252903211,"owners_count":21822395,"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":["counterculture","incremental","jsx","kefir","observables","react","reactive","vdom"],"created_at":"2024-11-17T22:06:50.365Z","updated_at":"2025-05-07T15:23:23.162Z","avatar_url":"https://github.com/calmm-js.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# \u003ca id=\"karet\"\u003e\u003c/a\u003e [≡](#contents) [▶](https://calmm-js.github.io/karet/index.html#karet) [Karet](#karet) \u0026middot; [![Gitter](https://img.shields.io/gitter/room/calmm-js/chat.js.svg)](https://gitter.im/calmm-js/chat) [![GitHub stars](https://img.shields.io/github/stars/calmm-js/karet.svg?style=social)](https://github.com/calmm-js/karet) [![npm](https://img.shields.io/npm/dm/karet.svg)](https://www.npmjs.com/package/karet)\n\nKaret is a library that allows you to embed\n[Kefir](https://kefirjs.github.io/kefir/) properties into\n[React](https://facebook.github.io/react/) Virtual DOM. Embedding observable\nproperties into VDOM has the following benefits:\n\n- It allows you to use only\n  [functional components](https://facebook.github.io/react/docs/components-and-props.html#functional-and-class-components),\n  because you can then use observables for managing state and component\n  lifetime, leading to more **_concise code_**.\n- It helps you to use React in an **_algorithmically efficient_** way:\n  - The body of a functional component is evaluated only once each time the\n    component is mounted.\n  - Only elements that contain embedded properties are rerendered when changes\n    are pushed through observables. An update to a deeply nested VDOM element\n    can be an `O(1)` operation.\n\nUsing Karet couldn't be simpler. Usually you just\n`import * as React from 'karet'` and you are good to go.\n\n[![npm version](https://badge.fury.io/js/karet.svg)](http://badge.fury.io/js/karet)\n[![Gitter](https://img.shields.io/gitter/room/calmm-js/chat.js.svg)](https://gitter.im/calmm-js/chat)\n[![Build Status](https://travis-ci.org/calmm-js/karet.svg?branch=master)](https://travis-ci.org/calmm-js/karet)\n[![Code Coverage](https://img.shields.io/codecov/c/github/calmm-js/karet/master.svg)](https://codecov.io/github/calmm-js/karet?branch=master)\n[![](https://david-dm.org/calmm-js/karet.svg)](https://david-dm.org/calmm-js/karet)\n[![](https://david-dm.org/calmm-js/karet/dev-status.svg)](https://david-dm.org/calmm-js/karet?type=dev)\n\n## \u003ca id=\"contents\"\u003e\u003c/a\u003e [≡](#contents) [▶](https://calmm-js.github.io/karet/index.html#contents) [Contents](#contents)\n\n- [Tutorial](#tutorial)\n- [Reference](#reference)\n  - [React exports passed through](#react-exports-passed-through)\n  - [`karet-lift` attribute](#karet-lift)\n  - [`fromClass(Component)`](#fromClass 'fromClass: Component props -\u003e Component (Property props)')\n  - [Known gotchas](#known-gotchas)\n\n## \u003ca id=\"tutorial\"\u003e\u003c/a\u003e [≡](#contents) [▶](https://calmm-js.github.io/karet/index.html#tutorial) [Tutorial](#tutorial)\n\nTo use Karet, you simply import it as `React`:\n\n```jsx\nimport * as React from 'karet'\n```\n\nand you can then write React components:\n\n```jsx\nconst App = () =\u003e (\n  \u003cdiv\u003e\n    \u003ch1\u003eWhat is the date and time\u003c/h1\u003e\n    {Kefir.interval(1000)\n      .toProperty(() =\u003e {})\n      .map(() =\u003e new Date().toString())}\n  \u003c/div\u003e\n)\n```\n\nwith VDOM that can have embedded [Kefir](https://kefirjs.github.io/kefir/)\nproperties. This works because Karet exports an enhanced version of\n`createElement`.\n\nNote that the result, like the date and time display above, is _just_ a React\ncomponent. If you export it, you can use it just like any other React component\nand even in modules that do not import `karet`.\n\n[Here is a live example in CodeSandbox](https://codesandbox.io/s/2o1mmnwxvp).\n\n[More links to live examples in the Calmm documentation Wiki](https://github.com/calmm-js/documentation/wiki/Links-to-live-examples).\n\n## \u003ca id=\"reference\"\u003e\u003c/a\u003e [≡](#contents) [▶](https://calmm-js.github.io/karet/index.html#reference) [Reference](#reference)\n\n### \u003ca id=\"react-exports-passed-through\"\u003e\u003c/a\u003e [≡](#contents) [▶](https://calmm-js.github.io/karet/index.html#react-exports-passed-through) [React exports passed through](#react-exports-passed-through)\n\nKaret passes through the following exports from React:\n\n- [`Children`](https://reactjs.org/docs/react-api.html#reactchildren) as is.\n  Note that with observable properties in children these functions may not do\n  exactly what you want and you might want to\n  [lift](https://github.com/calmm-js/karet.util#lifting) them.\n- [`Fragment`](https://reactjs.org/docs/fragments.html) as is. It should work\n  without problems.\n- [`createContext`](https://reactjs.org/docs/context.html#reactcreatecontext) as\n  is. Note that with Karet it is preferable to put observable properties into\n  the context and let changes propagate through them rather than update the\n  context. Also note that neither the provider nor the consumer are lifted by\n  default. Lifting the consumer will likely cause no issues, but lifting the\n  provider would eliminate observables from the `value` property and could cause\n  problems. If you need to have observable children inside the provider, you can\n  wrap the children inside a\n  [`Fragment`](https://reactjs.org/docs/fragments.html). See the CodeSandbox\n  examples\n  - [Exam Events Form](https://codesandbox.io/s/x20w218owo) where the context is\n    used to transmit the language as an observable atom, and\n  - [Form using Context](https://codesandbox.io/s/2rq54pgrp) where context is\n    used to transmit form properties to form elements.\n- [`createElement`](https://reactjs.org/docs/react-api.html#createelement) which\n  lifts Kefir properties in [fragments](https://reactjs.org/docs/fragments.html)\n  and built-in HTML elements.\n- [`forwardRef`](https://reactjs.org/docs/react-api.html#reactforwardref) as is.\n- [`useContext`](https://reactjs.org/docs/hooks-reference.html#usecontext) as\n  is.\n\nNotably the following are not exported:\n\n- [`Component`](https://reactjs.org/docs/react-api.html#reactcomponent) and\n  [`PureComponent`](https://reactjs.org/docs/react-api.html#reactpurecomponent),\n  because with Karet you really don't need them and the `render` method can\n  cause undesired component remounting when used with observable properties\n  embedded into VDOM.\n- [`cloneElement`](https://reactjs.org/docs/react-api.html#cloneelement) does\n  not work out of the box with elements containing Kefir properties. It should\n  be possible [to support it](https://github.com/calmm-js/karet/issues/6),\n  however.\n- [`createRef`](https://reactjs.org/docs/react-api.html#reactcreateref) is not\n  exported, because [Karet Util](https://github.com/calmm-js/karet.util)\n  provides an [alternative](https://github.com/calmm-js/karet.util/#U-refTo)\n  that works better with observable properties.\n- [`Suspense` and `lazy`](https://reactjs.org/docs/react-api.html#reactsuspense)\n  are not needed since `import()` returns a promise and you can just convert\n  that to an observable property\n  [like this](https://codesandbox.io/s/n5mvx6v69m).\n- [Most React hooks](https://reactjs.org/docs/hooks-reference.html) are not\n  exported because they are not typically needed in Karet components. State\n  should be handled in [atoms](https://github.com/calmm-js/kefir.atom). Effects\n  can already be handled using observable properties as children or props.\n\n### \u003ca id=\"karet-lift\"\u003e\u003c/a\u003e [≡](#contents) [▶](https://calmm-js.github.io/karet/index.html#karet-lift) [`karet-lift` attribute](#karet-lift)\n\nKaret only lifts built-in HTML elements and\n[fragments](https://reactjs.org/docs/fragments.html) implicitly. The\n`karet-lift` attribute on a non-primitive element instructs Karet to lift the\nelement.\n\nFor example, you could write:\n\n```jsx\nimport Select from 'react-select'\nimport * as React from 'karet'\n\n// ...\n\nconst ReactSelect1 = ({value}) =\u003e (\n  \u003cSelect\n    karet-lift\n    name=\"form-field-name\"\n    value={value}\n    options={options}\n    onChange={o =\u003e value.set(o \u0026\u0026 o.value)}\n  /\u003e\n)\n```\n\nto be able to use `Select` from\n[React Select](https://github.com/JedWatson/react-select) with embedded\n[Kefir Atoms](https://github.com/calmm-js/kefir.atom).\n\n[Here is a live example in CodeSandbox](https://codesandbox.io/s/7yjj16jz7q).\n\n### \u003ca id=\"fromClass\"\u003e\u003c/a\u003e [≡](#contents) [▶](https://calmm-js.github.io/karet/index.html#fromClass) [`fromClass(Component)`](#fromClass 'fromClass: Component props -\u003e Component (Property props)')\n\nKaret only lifts built-in HTML elements and\n[fragments](https://reactjs.org/docs/fragments.html) implicitly. `fromClass`\nallows one to create lifted version of a given React component.\n\nFor example, you could write:\n\n```jsx\nimport Select from 'react-select'\nimport * as React from 'karet'\n\nconst SelectLifted = React.fromClass(Select)\n\nconst ReactSelect2 = ({value}) =\u003e (\n  \u003cSelectLifted\n    name=\"form-field-name\"\n    value={value}\n    options={options}\n    onChange={o =\u003e value.set(o \u0026\u0026 o.value)}\n  /\u003e\n)\n```\n\nto be able to use `Select` from\n[React Select](https://github.com/JedWatson/react-select) with embedded\n[Kefir Atoms](https://github.com/calmm-js/kefir.atom).\n\n[Here is a live example in CodeSandbox](https://codesandbox.io/s/7yjj16jz7q).\n\n### \u003ca id=\"known-gotchas\"\u003e\u003c/a\u003e [≡](#contents) [▶](https://calmm-js.github.io/karet/index.html#known-gotchas) [Known gotchas](#known-gotchas)\n\nThe\n[React inline elements transform ](https://babeljs.io/docs/plugins/transform-react-inline-elements/)\nis incompatible with Karet, because it bypasses `React.createElement`. OTOH, the\n[React constant elements transform](https://babeljs.io/docs/plugins/transform-react-constant-elements/)\nworks just fine with Karet.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcalmm-js%2Fkaret","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcalmm-js%2Fkaret","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcalmm-js%2Fkaret/lists"}