{"id":19353618,"url":"https://github.com/benwiley4000/bind-cache","last_synced_at":"2025-02-24T10:48:54.405Z","repository":{"id":143735462,"uuid":"144082169","full_name":"benwiley4000/bind-cache","owner":"benwiley4000","description":"➰ Bound method cache, ideal for React","archived":false,"fork":false,"pushed_at":"2018-08-09T02:16:21.000Z","size":15,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-16T03:06:32.905Z","etag":null,"topics":["bind","bound","cache","method","react"],"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/benwiley4000.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-09T00:36:32.000Z","updated_at":"2019-01-22T23:34:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"ff074328-ab40-4402-adfe-89890382c2ae","html_url":"https://github.com/benwiley4000/bind-cache","commit_stats":{"total_commits":11,"total_committers":2,"mean_commits":5.5,"dds":0.09090909090909094,"last_synced_commit":"4e1babdb9c7586865913f05a89552411e91e3782"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benwiley4000%2Fbind-cache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benwiley4000%2Fbind-cache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benwiley4000%2Fbind-cache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benwiley4000%2Fbind-cache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/benwiley4000","download_url":"https://codeload.github.com/benwiley4000/bind-cache/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240466743,"owners_count":19805860,"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":["bind","bound","cache","method","react"],"created_at":"2024-11-10T04:43:31.447Z","updated_at":"2025-02-24T10:48:54.386Z","avatar_url":"https://github.com/benwiley4000.png","language":"JavaScript","readme":"# bind-cache\n\nCreates a cache of bound JavaScript functions created with [`Function.prototype.bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind).\n\n* Only one instance is ever created for each unique set of arguments\n* Designed to be allocated only for the lifetime of an associated object\n* Works for binding call arguments to a method\n* Ideal for React components\n* 1.27 KB (unminfied)\n\n## usage\n\n```jsx\nclass MyComponent extends React.Component {\n  constructor(props) {\n    super(props);\n    this.message = 'Hello World';\n\n    // cache is garbage-collected whenever the\n    // MyComponent instance is garbage-collected\n    this.bind = bindCache(this);\n  }\n\n  handleClick() {\n    alert(this.message);\n  }\n\n  render() {\n    // across multiple renders, only one bound instance of this.handleClick\n    // is ever created for this instance of MyComponent\n    return \u003cMyButton onClick={this.bind(this.handleClick)}\u003eClick Me\u003c/MyButton\u003e;\n  }\n}\n```\n\n### pass arguments to bound function\n\n```jsx\n  // ...\n  handleClick(index) {\n    alert(this.message + ' (index: ' + index + ')');\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        {this.props.dataList.map((data, i) =\u003e\n          // across multiple renders, only one bound instance of\n          // this.handleClick is created for each member of this.props.dataList\n          \u003cMyButton onClick={this.bind(this.handleClick, i)}\u003e{data}\u003c/MyButton\u003e\n        )}\n      \u003c/div\u003e\n    );\n  }\n}\n```\n\n## install\n\nWith npm:\n\n```console\nnpm install @benwiley4000/bind-cache\n```\n\nUsing a script tag:\n\n```html\n\u003cscript src=\"https://unpkg.com/@benwiley4000/bind-cache\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  console.log(bindCache); // should be a function\n\u003c/script\u003e\n```\n\n### dependencies\n\nThis library is written in plain ES5 JavaScript so it will run in any browser you'll need to support, but you might need to polyfill [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Browser_compatibility) and [`Symbol`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#Browser_compatibility) to support older browsers.\n\nFor compatibility, pass your substitutions for `Map` and `Symbol` in the optional second argument to `bindCache`:\n\n```js\nthis.bind = bindCache(this, { Map: MapPolyfill, Symbol: SymbolPolyfill });\n```\n\nFor `Map` you can try the [`es6-map` package](https://github.com/medikoo/es6-map).\n\nFor `Symbol` you can try the [`es6-symbol` package](https://www.npmjs.com/package/es6-symbol).\n\nHowever if you prefer something less heavy you can probably get away with the following:\n\n```js\nfunction SymbolPolyfill() {\n  // this should return something that you will NEVER pass\n  // as an argument to bind - otherwise something could go wrong.\n  return 1.513543544;\n}\n```\n\n## API\n\n### `bindCache(objectInstance[, options])`\n\nallocates a new cache (optionally with `Map` and `Symbol` fallbacks) and returns a function `bind` which looks like:\n\n### `bind(functionToBind[, ...callArguments])`\n\nEach call to `bind(...)` returns a function bound to `objectInstance` (and optionally to an additional list of call arguments).\n\nThe cache is never emptied and lasts as long as `bind` is referenced somewhere in the application (after which it will be garbage-collected).\n\n## why\n\nIn some cases a JavaScript class instance needs to pass one of its member methods around as a callback argument. Generally this method sound be bound to the class instance before being passed so that when invoked it will have access to the `this` context of that particular instance.\n\n```jsx\n  render() {\n    // each time render is called, we bind a copy of handleClick to the\n    // instance and pass it to our MyButton child as an onClick prop\n    return \u003cMyButton onClick={this.handleClick.bind(this)}\u003eClick Me\u003c/MyButton\u003e;\n  }\n```\n\nIn the world of React components in particular (and perhaps others), it's typically desirable to bind the method only once and pass that bound method many times in the render method. Creating a new bound instance on each render can cause unnecessary re-renders in child components.\n\nTypically this approach takes one of two forms:\n* Bind in the constructor\n    ```jsx\n    class MyComponent extends React.Component {\n      constructor(props) {\n        super(props);\n        // when the instance is created, we grab our methods\n        // from the prototype and created bound copies on\n        // the instance\n        this.handleClick = this.handleClick.bind(this);\n        this.handleHover = this.handleHover.bind(this);\n        this.handleBlur = this.handleBlur.bind(this);\n      }\n      \n      // ... method definitions\n\n      render() {\n        return \u003cMyButton onClick={this.handleClick}\u003eClick Me\u003c/MyButton\u003e;\n      }\n    }\n    ```\n* Use arrow function class \"methods\"\n    ```jsx\n    class MyComponent extends React.Component {\n      // when the instance is created, we create new\n      // arrow function members bound to our instance\n      handleClick = () =\u003e {\n        // ...\n      };\n\n      handleHover = () =\u003e {\n        // ...\n      };\n\n      handleBlur = () =\u003e {\n        // ...\n      };\n\n      render() {\n        return \u003cMyButton onClick={this.handleClick}\u003eClick Me\u003c/MyButton\u003e;\n      }\n    }\n    ```\n\nEach of these approaches can be problematic:\n* Binding in the constructor introduces a lot of boilerplate that is annoying to maintain\n* Binding with arrow function members relies on the JavaScript [class fields proposal](https://github.com/tc39/proposal-class-fields) which has not yet made it into the ECMAScript specification\n* Binding with arrow function members also means our methods are excluded from the class prototype, which can be a problem for testing, or if you are overriding a method in a derived class (rare in the React world, but certainly possible)\n* Each approach doesn't lend itself well to cases where functions need to be bound with additional call arguments. That case comes up when, for instance, an array of children needs to be rendered, each with a bound callback prop.\n\n`bindCache` avoids all of the above problems.\n\n## comparisons to prior work\n\n[cached-bind](https://github.com/megazazik/cached-bind) by megazazik solves the same issues, but bind-cache has a few advantages:\n* Doesn't modify the object\n* No need for a `key` argument\n* Much simpler/smaller implementation (plain ES5)\n\nHowever cached-bind doesn't require `Map` or `Symbol`, so it can work without polyfills in older browsers.\n\n## contributing\n\nPlease feel free to open a pull request with test cases or bug fixes.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenwiley4000%2Fbind-cache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbenwiley4000%2Fbind-cache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenwiley4000%2Fbind-cache/lists"}