{"id":19472353,"url":"https://github.com/aboutbits/react-toolbox","last_synced_at":"2025-04-25T12:31:23.162Z","repository":{"id":41183632,"uuid":"359689317","full_name":"aboutbits/react-toolbox","owner":"aboutbits","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-20T10:54:03.000Z","size":247,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-20T13:07:32.187Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/aboutbits.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.md","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":"2021-04-20T05:00:46.000Z","updated_at":"2025-03-20T10:54:06.000Z","dependencies_parsed_at":"2025-03-20T11:30:43.411Z","dependency_job_id":"fb3984c1-3ffb-4982-974c-33cab5146c93","html_url":"https://github.com/aboutbits/react-toolbox","commit_stats":{"total_commits":36,"total_committers":7,"mean_commits":5.142857142857143,"dds":0.5555555555555556,"last_synced_commit":"3d2946b454a44a8799d2c5df232f3921e7ecd890"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutbits%2Freact-toolbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutbits%2Freact-toolbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutbits%2Freact-toolbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutbits%2Freact-toolbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aboutbits","download_url":"https://codeload.github.com/aboutbits/react-toolbox/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250817627,"owners_count":21492187,"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-11-10T19:14:11.664Z","updated_at":"2025-04-25T12:31:22.595Z","avatar_url":"https://github.com/aboutbits.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Toolbox\n\n[![npm package](https://badge.fury.io/js/%40aboutbits%2Freact-toolbox.svg)](https://badge.fury.io/js/%40aboutbits%2Freact-toolbox)\n[![license](https://img.shields.io/github/license/aboutbits/react-toolbox)](https://github.com/aboutbits/react-toolbox/blob/main/license.md)\n\nThis package includes different tools that support you with common tasks.\n\n## Table of content\n\n- [Usage](#usage)\n  - [useInterval](#useinterval)\n  - [Async Data](#async-data)\n  - [LocationProvider](#locationprovider)\n  - [useMatchMediaQuery](#usematchmediaquery)\n  - [useDebounce](#usedebounce)\n  - [useIsMounted](#useismounted)\n- [Build \u0026 Publish](#build--publish)\n- [Information](#information)\n\n## Usage\n\nFirst, you have to install the package:\n\n```bash\nnpm install @aboutbits/react-toolbox\n```\n\nSecond, you can make use of the different tools.\n\n### useInterval\n\nThe `useInterval` hook calls a function at specified intervals. The code of this hook is taken from [Dan Abramov's blog post](https://overreacted.io/making-setinterval-declarative-with-react-hooks/).\n\nThe hook takes two parameters:\n\n- `callback`: The callback function that should be executed.\n- `delay`: The delay in milliseconds or null, if the interval should be paused.\n\n```tsx\nimport React, { useState } from 'react'\nimport { useInterval } from '@aboutbits/react-toolbox'\n\nconst MyCommponent = () =\u003e {\n  const [step, setStep] = useState(10)\n\n  useInterval(\n    () =\u003e {\n      setStep(step - 1)\n    },\n    step === 0 ? null : 1000\n  )\n\n  return \u003cp\u003eCountdown: {step}\u003c/p\u003e\n}\n```\n\n### Async Data\n\nThis part includes a utility component, that can be used to render loading, success and error views based on async state.\n\n```tsx\nimport React, { useEffect } from 'react'\nimport { AsyncView } from '@aboutbits/react-toolbox'\n\ntype Data = {\n  greeting: string\n}\n\ntype Error = {\n  message: string\n}\n\nconst MyCommponent = () =\u003e {\n  const [data, setData] = useState\u003cData | undefined\u003e()\n  const [error, setError] = useState\u003cError | undefined\u003e()\n\n  useEffect(() =\u003e {\n    fetch('https://jsonplaceholder.typicode.com/todos/1')\n      .then((response) =\u003e setData(response.json()))\n      .catch((error) =\u003e setError(error))\n  })\n\n  return (\n    \u003cAsyncView\n      data={data}\n      error={error}\n      renderLoading={\u003cdiv\u003eLoading\u003c/div\u003e}\n      renderSuccess={(data) =\u003e \u003cdiv\u003e{data.greeting}\u003c/div\u003e}\n      renderError={(error) =\u003e \u003cdiv\u003e{error.message}\u003c/div\u003e}\n    /\u003e\n  )\n}\n```\n\nAnd using SWR:\n\n```tsx\nimport React, { useEffect } from 'react'\nimport { useSWR } from 'swr'\nimport { AsyncView } from '@aboutbits/react-toolbox'\n\ntype Data = {\n  greeting: string\n}\n\ntype Error = {\n  message: string\n}\n\nconst MyCommponent = () =\u003e {\n  const { data, error } = useSWR('https://jsonplaceholder.typicode.com/todos/1')\n\n  return (\n    \u003cAsyncView\n      data={data}\n      error={error}\n      renderLoading={'Loading'}\n      renderSuccess={'Success'}\n      renderError={'Error'}\n    /\u003e\n  )\n}\n```\n\n### LocationProvider\n\nThis part includes a React context that fetches the geolocation at a given interval.\n\n```tsx\nimport { LocationProvider } from '@aboutbits/react-toolbox'\n\nconst MyApp = () =\u003e {\n  return (\n    \u003cLocationProvider highAccuracy={true} delay={20000}\u003e\n      {children}\n    \u003c/LocationProvider\u003e\n  )\n}\n```\n\nThe context provider takes two props:\n\n- `highAccuracy`: defines if the location should be fetched with high accuracy. Read more on the [Geolocation API doc](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API).\n- `delay`: the delay in milliseconds between each fetch\n\n```tsx\nimport { useContext } from 'react'\nimport { LocationContext } from '@aboutbits/react-toolbox'\n\nconst MyComponent = () =\u003e {\n  const { location } = useContext(LocationContext)\n\n  return location ? (\n    \u003cdiv\u003e\n      Your location is: {location.coords.latitude}, {location.coords.longitude}\n    \u003c/div\u003e\n  ) : (\n    \u003cdiv\u003eUnable to get your location\u003c/div\u003e\n  )\n}\n```\n\n### useMatchMediaQuery\n\nThis hook is based on the `window.matchQuery` API and can be used to find out if a certain media query matches the current window.\n\n```tsx\nimport { useMatchMediaQuery } from '@aboutbits/react-toolbox'\n\nconst TestComponent = () =\u003e {\n  const matches = useMatchMediaQuery('(min-width : 500px)')\n  if (matches) return \u003cdiv\u003evisible\u003c/div\u003e\n  return null\n}\n```\n\n### useDebounce\n\nUse this hook to prevent the component from re-rendering too many times. Useful to avoid making unnecessary API calls.\n\n```tsx\nexport default function TestComponent() {\n  const [value, setValue] = useState('')\n  const debouncedValue = useDebounce(value, 500)\n\n  const handleChange = (event: ChangeEvent\u003cHTMLInputElement\u003e) =\u003e {\n    setValue(event.target.value)\n  }\n\n  // Fetch API (optional)\n  useEffect(() =\u003e {\n    // Do fetch here...\n    // Triggers when \"debouncedValue\" changes\n  }, [debouncedValue])\n\n  return (\n    \u003cdiv\u003e\n      \u003cp\u003eValue real-time: {value}\u003c/p\u003e\n      \u003cp\u003eDebounced value: {debouncedValue}\u003c/p\u003e\n      \u003cinput type=\"text\" value={value} onChange={handleChange} /\u003e\n    \u003c/div\u003e\n  )\n}\n```\n\n### useIsMounted\n\nIn React, a component is deleted from memory once unmounted. Changing the state in an unmounted component will result in an error.\nThis is preferrably solved passing a cleanup function to [useEffect](https://react.dev/reference/react/useEffect#useeffect).\nHowever, there are some cases like Promise or API calls where it's impossible to know if the component is still mounted at the resolve time.\nThis hook returns a function that can be used to verify at the resolve time whether the component is still mounted.\n\n```tsx\nconst delay = (ms: number) =\u003e new Promise((resolve) =\u003e setTimeout(resolve, ms))\n\nfunction Child() {\n  const [data, setData] = useState('loading')\n  const isMounted = useIsMounted()\n\n  // simulate an api call and update state\n  useEffect(() =\u003e {\n    void delay(3000).then(() =\u003e {\n      if (isMounted()) {\n        setData('OK')\n      }\n    })\n  }, [isMounted])\n\n  return \u003cp\u003e{data}\u003c/p\u003e\n}\n\nexport default function TestComponent() {\n  const [isVisible, setVisible] = useState\u003cboolean\u003e(false)\n\n  const toggleVisibility = () =\u003e setVisible((state) =\u003e !state)\n\n  return (\n    \u003c\u003e\n      \u003cbutton onClick={toggleVisibility}\u003e{isVisible ? 'Hide' : 'Show'}\u003c/button\u003e\n\n      {isVisible \u0026\u0026 \u003cChild /\u003e}\n    \u003c/\u003e\n  )\n}\n```\n\n## Build \u0026 Publish\n\nTo publish the package commit all changes and push them to main. Then run one of the following commands locally:\n\n```bash\nnpm version patch\nnpm version minor\nnpm version major\n```\n\n## Information\n\nAbout Bits is a company based in South Tyrol, Italy. You can find more information about us on [our website](https://aboutbits.it).\n\n### Support\n\nFor support, please contact [info@aboutbits.it](mailto:info@aboutbits.it).\n\n### Credits\n\n- [Martin Malfertheiner](https://github.com/mmalfertheiner)\n- [Alex Lanz](https://github.com/alexlanz)\n- [All Contributors](../../contributors)\n\n### License\n\nThe MIT License (MIT). Please see the [license file](license.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faboutbits%2Freact-toolbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faboutbits%2Freact-toolbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faboutbits%2Freact-toolbox/lists"}