{"id":13496404,"url":"https://github.com/jaredpalmer/mutik","last_synced_at":"2025-04-07T10:28:27.778Z","repository":{"id":42919809,"uuid":"246930596","full_name":"jaredpalmer/mutik","owner":"jaredpalmer","description":"A tiny (495B) immutable state management library based on Immer","archived":false,"fork":false,"pushed_at":"2023-01-07T15:54:06.000Z","size":1012,"stargazers_count":325,"open_issues_count":26,"forks_count":8,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-31T09:04:33.827Z","etag":null,"topics":["immer","react","state-management"],"latest_commit_sha":null,"homepage":"https://npm.im/mutik","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/jaredpalmer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["jaredpalmer"]}},"created_at":"2020-03-12T21:04:01.000Z","updated_at":"2024-11-02T07:36:16.000Z","dependencies_parsed_at":"2023-02-07T14:16:16.909Z","dependency_job_id":null,"html_url":"https://github.com/jaredpalmer/mutik","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredpalmer%2Fmutik","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredpalmer%2Fmutik/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredpalmer%2Fmutik/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredpalmer%2Fmutik/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jaredpalmer","download_url":"https://codeload.github.com/jaredpalmer/mutik/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247634857,"owners_count":20970618,"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":["immer","react","state-management"],"created_at":"2024-07-31T19:01:47.430Z","updated_at":"2025-04-07T10:28:27.757Z","avatar_url":"https://github.com/jaredpalmer.png","language":"TypeScript","readme":"\u003cimg width=\"243\" alt=\"Mutik\" src=\"https://user-images.githubusercontent.com/4060187/76576100-81dff980-6497-11ea-93fd-52fc765b9fdc.png\"\u003e\n\n\u003e A tiny (495B) immutable state management library based on Immer\n\n## Quick Start\n\n```bash\nyarn add mutik\n```\n\nor\n\n[![Edit Mutik](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/mutik-2so66?fontsize=14\u0026hidenavigation=1\u0026theme=dark)\n\n**Table of Contents**\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n- [Example](#example)\n- [API](#api)\n  - [`createStore\u003cS\u003e(intialState: S): Store\u003cS\u003e`](#createstoresintialstate-s-stores)\n    - [`store`](#store)\n  - [`useSelector\u003cS, V\u003e(selector: (s: S) =\u003e V)`](#useselectors-vselector-s-s--v)\n  - [`\u003cProvider /\u003e`](#provider-)\n- [Author](#author)\n- [Inspiration](#inspiration)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Example\n\nTo use Mutik with React, you'll need to install React and React DOM from the experimental release channel because Mutik uses the recently-merged `useMutableSource` hook internally.\n\n```bash\nyarn add react@experimental react-dom@experimental\n```\n\n```jsx\nimport React from 'react';\nimport { render } from 'react-dom';\nimport { createStore, Provider, useSelector } from 'mutik';\n\n// Create a lil' store with some state\nlet store = createStore({\n  count: 0,\n});\n\n// Pass the store to the Provider.\nfunction App() {\n  return (\n    \u003cProvider store={store}\u003e\n      \u003cdiv\u003e\n        \u003cLabel /\u003e\n        \u003cButtons /\u003e\n      \u003c/div\u003e\n    \u003c/Provider\u003e\n  );\n}\n\n// You can mutate the store from anywhere you want to,\n// even outside of React code. Mutate is based on immer.\nfunction increment() {\n  store.mutate(state =\u003e {\n    state.count++;\n  });\n}\n\n// Or you can update it like React.useState's update\nfunction decrement() {\n  store.set(prevState =\u003e ({\n    ...prevState,\n    count: prevState.count - 1\n  });\n}\n\n// You don't need to pass the store down as a prop either\nfunction Buttons() {\n  return (\n    \u003cReact.Fragment\u003e\n      \u003cbutton onClick={decrement}\u003e-\u003c/button\u003e\n      \u003cbutton onClick={increment}\u003e+\u003c/button\u003e\n    \u003c/React.Fragment\u003e\n  );\n}\n\n// Lastly, you can subcribe to \"slices\" of state with useSelector\n// Note: be sure to memoize these with React.useCallback if you need to select based on props\nfunction Label() {\n  const selector = React.useCallback(state =\u003e state.count, []);\n  const count = useSelector(selector);\n  return \u003cp\u003eThe count is {count}\u003c/p\u003e;\n}\n\nrender(\u003cApp /\u003e, window.root);\n```\n\n## API\n\n### `createStore\u003cS\u003e(intialState: S): Store\u003cS\u003e`\n\nCreate a Mutik `store` given some initial state. The `store` has the following API you can use in or out of React.\n\n#### `store`\n\n| **Method**                                            | **Description**                                                                                                                                 |\n| ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |\n| `get()`                                               | Get the current state. Do not use this inside of React, you should instead use [`useSelector`](#useselectors-vselector-s-s--v)                  |\n| `set(nextState: S \\| (prevState: S) =\u003e V): void;`     | Set state. This can either take a new value or and updater function (just like React.useState's updater)                                        |\n| `on(listener: Function): () =\u003e void;`                 | Subscribe to store. Pass in a callback function that will be executed on updates. `on()` returns the unsubscribe function for your convenience. |\n| `off(listener: Function): void;`                      | Unsubscribe a given listener function                                                                                                           |\n| `reset(): void`                                       | Set state back to the `initialState` used when creating the store                                                                               |\n| `mutate(updater: (draft: Draft) =\u003e void \\| S): void;` | Immer-style updater function.                                                                                                                   |\n\n### `useSelector\u003cS, V\u003e(selector: (s: S) =\u003e V)`\n\nReact hook to subscribe to Mutik state. Must be called underneath a Mutik `Provider`.\n\n```jsx\nconst selector = state =\u003e state.count;\n\nfunction Label() {\n  const count = useSelector(selector);\n  return \u003cp\u003eThe count is {count}\u003c/p\u003e;\n}\n```\n\nYou can use props with Mutik selector. For performance, it's a good idea to memoize the selector with `React.useCallback`. For example:\n\n```jsx\nfunction User({ id }) {\n  const selector = React.useCallback(state =\u003e state.users[id], [id]);\n  const user = useSelector(selector);\n  return \u003cp\u003eThe username is {user.name}\u003c/p\u003e;\n}\n```\n\n### `\u003cProvider /\u003e`\n\nMutik context provider. Pass your store as `store` prop. For example:\n\n```jsx\nimport React from 'react';\nimport { createStore, Provider } from 'mutik';\n\n// Create a lil' store with some state\nlet store = createStore({\n  count: 0,\n});\n\n// Pass the store to the Provider.\nfunction App() {\n  return (\n    \u003cProvider store={store}\u003e\n      \u003cdiv\u003e{/* ... stuff */}\u003c/div\u003e\n    \u003c/Provider\u003e\n  );\n}\n```\n\n## Author\n\n- Jared Palmer [@jaredpalmer](https://twitter.com/jaredpalmer)\n\n## Inspiration\n\n- [bey](https://github.com/jamiebuilds/bey)\n- [react-copy-write](https://github.com/aweary/react-copy-write)\n- [Brian Vaughn's fake redux](https://codesandbox.io/s/react-redux-usemutablesource-eyxoe)\n\n---\n\n\u003e MIT License\n","funding_links":["https://github.com/sponsors/jaredpalmer"],"categories":["TypeScript","Uncategorized","Framework agnostic packages"],"sub_categories":["Uncategorized","Immutable"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaredpalmer%2Fmutik","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaredpalmer%2Fmutik","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaredpalmer%2Fmutik/lists"}