{"id":17274600,"url":"https://github.com/rip21/react-hanger-clone-for-course","last_synced_at":"2025-03-26T13:41:39.834Z","repository":{"id":145840346,"uuid":"293322601","full_name":"RIP21/react-hanger-clone-for-course","owner":"RIP21","description":"Just a clone of react-hanger for a course that I'm making.","archived":false,"fork":false,"pushed_at":"2020-09-26T21:21:12.000Z","size":1074,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-31T15:11:15.168Z","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/RIP21.png","metadata":{"files":{"readme":"README-ARRAY.md","changelog":"CHANGELOG.md","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":"2020-09-06T17:00:03.000Z","updated_at":"2020-09-26T20:16:44.000Z","dependencies_parsed_at":"2023-05-05T19:36:12.391Z","dependency_job_id":null,"html_url":"https://github.com/RIP21/react-hanger-clone-for-course","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RIP21%2Freact-hanger-clone-for-course","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RIP21%2Freact-hanger-clone-for-course/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RIP21%2Freact-hanger-clone-for-course/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RIP21%2Freact-hanger-clone-for-course/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RIP21","download_url":"https://codeload.github.com/RIP21/react-hanger-clone-for-course/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245666168,"owners_count":20652728,"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-10-15T08:54:17.694Z","updated_at":"2025-03-26T13:41:39.808Z","avatar_url":"https://github.com/RIP21.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## API Reference (array destructuring)\n\n### How to import?\n\n```\nimport { useBoolean } from 'react-hanger/array' // will import all of functions\nimport useBoolean from 'react-hanger/array/useBoolean' // will import only this function\n```\n\n### useBoolean\n\n```jsx\nconst [showCounter, actions] = useBoolean(true);\n```\n\nActions:\n\n- `toggle`\n- `setTrue`\n- `setFalse`\n\n### useNumber\n\n```jsx\nconst [counter] = useNumber(0);\nconst [limitedNumber] = useNumber(3, { upperLimit: 5, lowerLimit: 3 });\nconst [rotatingNumber] = useNumber(0, {\n  upperLimit: 5,\n  lowerLimit: 0,\n  loop: true\n});\n```\n\nActions:\n\nBoth `increase` and `decrease` take an optional `amount` argument which is 1 by default, and will override the `step` property if it's used in the options.\n\n- `increase(amount = 1)`\n- `decrease(amount = 1 )`\n\nOptions:\n\n- `lowerLimit`\n- `upperLimit`\n- `loop`\n- `step` - sets the increase/decrease amount of the number upfront, but it can still be overriden by `number.increase(3)` or `number.decrease(5)`\n\n### useInput\n\nThis one is unique, since it returns tuple as a first element, where first element is `value` and second is `hasValue`\nSecond element is `actions` as usual\n\n```typescript\ntype UseInputActions = {\n  setValue: React.Dispatch\u003cSetStateAction\u003cstring\u003e\u003e;\n  onChange: (e: React.SyntheticEvent) =\u003e void\n  clear: () =\u003e void\n}\ntype UseInput = [[string, boolean], UseInputActions]\n```\n\n```jsx\nconst [[newTodo], actions] = useInput(\"\");\n```\n\n```jsx\n\u003cinput value={newTodo} onChange={actions.onChange} /\u003e\n```\nActions:\n\n- `clear`\n- `onChange` - default native event.target.value handler\n\nProperties:\n\n- `hasValue` -\n\n### useBindToInput\n\nDesigned to be used in composition with `useInput`.\nFirst and second elements are the same as `useInput.\nThird are bindings to spread.\n\n```jsx\nconst [[newTodo], actions, { nativeBind, valueBind }] = useBindToInput(useInput(\"\"));\n```\n\n```jsx\n\u003cinput value={newTodo} onChange={actions.onChange} /\u003e\n\u003cinput {...nativeBind} /\u003e\n\u003cSlider {...valueBind} /\u003e\n```\n\nActions:\n\n- `nativeBind` - binds the `value` and `onChange` props to an input that has `e.target.value`\n- `valueBind` - binds the `value` and `onChange` props to an input that's using only `value` in `onChange` (like most external components)\n\n### useArray\n\n```jsx\nconst [todos, actions] = useArray([]);\n```\n\nActions:\n\n- `push`\n- `unshift`\n- `pop`\n- `shift`\n- `clear`\n- `removeIndex`\n- `removeById` - if array consists of objects with some specific `id` that you pass\nall of them will be removed\n- `modifyById` - if array consists of objects with some specific `id` that you pass\nthese elements will be modified.\n- `move` - moves item from position to position shifting other elements. \n```\n    So if input is [1, 2, 3, 4, 5]\n    \n    from  | to    | expected\n    3     | 0     | [4, 1, 2, 3, 5]\n    -1    | 0     | [5, 1, 2, 3, 4]\n    1     | -2    | [1, 3, 4, 2, 5]\n    -3    | -4    | [1, 3, 2, 4, 5]\n```\n\n### useMap\n\n```jsx\nconst [someMap, someMapActions] = useMap([[\"key\", \"value\"]]);\nconst [anotherMap, anotherMapActions] = useMap(new Map([[\"key\", \"value\"]]));\n```\n\nActions:\n\n- `set`\n- `delete`\n- `clear`\n- `initialize` - applies tuples or map instances\n- `setValue`\n \n\n## useSetState\n\n```jsx\nconst [state, setState, resetState] = useSetState({ loading: false });\nsetState({ loading: true, data: [1, 2, 3] });\n```\n\nActions:\n\n- `setState(value)` - will merge the `value` with the current `state` (like this.setState works in React)\n- `resetState()` - will reset the current `state` to the `value` which you pass to the `useSetState` hook\n\nProperties:\n\n- `state` - the current state\n\n## usePrevious\n\nUse it to get the previous value of a prop or a state value.  \nIt's from the official [React Docs](https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state).  \nIt might come out of the box in the future.\n\n```jsx\nconst Counter = () =\u003e {\n  const [count, setCount] = useState(0);\n  const prevCount = usePrevious(count);\n  return (\n    \u003ch1\u003e\n      Now: {count}, before: {prevCount}\n    \u003c/h1\u003e\n  );\n};\n```\n\n### Migration from object to array based\n\nAll value based hooks like `useBoolean`, `useNumber` etc. Are changed to \nbe using arrays, since it's more safe for reference equality, and also \nmakes it easier to use many `useSmth` without renaming `value` in destructuring.\n\nSo if you had \n```javascript\nconst { value: showHeader, ...showHeaderActions } = useBoolean(true)\nconst { value: showFooter, ...setShowFooterActions } = useBoolean(true)\n```\nIt will become\n```javascript\nconst [showHeader, showHeaderActions] = useBoolean(true)\nconst [showFooter, showFooterActions] = useBoolean(true)\n```\n\nNote that despite this code seems to be looking the same, it's not. Cause `showHeaderActions` in v1 will result\nin new object reference every rerender (because spreading creates new object, hence new reference). While in v2 actions are memoized \nusing `useMemo` and their reference will not change, cause they are not rely on value.\nIt enables us passing `actions` down the props without useless re-renders and excessive destructuring, it prevents `useEffects` and\nother hooks from re-run/new reference creation if autofix of ESLint rule `react-hooks/extraneous-deps` will add them as dependencies automatically.\n\n### useInput migration\nAlso big change to the `useInput`\nIf before you was not using `eventBind` and `nativeBind` from them, then using the same approach from above\nyou will get what you want. \nBut if you need bindings you need to compose `useInput` with `useBindToInput` like that:\nSo if you had\n```jsx\nconst { value, eventBind, valueBind, onChange, hasValue } = useInput(\"\")\n\n\u003cinput value={value} onChange={onChange} /\u003e\n\u003cinput {...eventBind} /\u003e\n{hasValue \u0026\u0026 \u003cSlider {...valueBind} /\u003e}\n```\nIt will become\n```jsx\nconst [[value, hasValue], actions, { eventBind, valueBind }] = useBindToInput(useInput(\"\"))\n\n\u003cinput value={value} onChange={actions.onChange} /\u003e\n\u003cinput {...eventBind} /\u003e\n{hasValue \u0026\u0026 \u003cSlider {...valueBind} /\u003e}\n```\n\nNote that first element in destructured array has tuple of `[value, hasValue]` since it's for values\nand second argument is for `actions` e.g. only for functions.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frip21%2Freact-hanger-clone-for-course","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frip21%2Freact-hanger-clone-for-course","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frip21%2Freact-hanger-clone-for-course/lists"}