{"_id":"@dominicprice/remotedata","name":"@dominicprice/remotedata","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@dominicprice/remotedata","version":"1.0.0","description":"Remote Data library for typescript","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","scripts":{"test":"jest","build":"tsup"},"repository":{"type":"git","url":"git+https://github.com/dominicprice/yard.git"},"keywords":["remote","data","typescript"],"author":{"name":"Dominic Price"},"license":"MIT","bugs":{"url":"https://github.com/dominicprice/yard/issues"},"homepage":"https://github.com/dominicprice/yard#readme","devDependencies":{"@types/jest":"^29.5.12","jest":"^29.7.0","ts-jest":"^29.1.2","ts-node":"^10.9.2","tsup":"^8.0.2","typescript":"^5.3.3"},"_id":"@dominicprice/remotedata@1.0.0","gitHead":"15e0d2ec520a54d22b1f1a5467b447b46d3ffb9e","_nodeVersion":"21.6.1","_npmVersion":"10.2.4","dist":{"integrity":"sha512-HCK3ckhxm6Lg1vtBBYKUl6oZDHNgMWy5gmi7krD8LLdMW2qQbk2AH3bp/54PA4osk102Fy4t/KL3YTFaLBly/Q==","shasum":"a6000a7cc4ea69d7802c730d13e847ff0f3b59ba","tarball":"https://registry.npmjs.org/@dominicprice/remotedata/-/remotedata-1.0.0.tgz","fileCount":9,"unpackedSize":29094,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFy93IXjcB/tRMjlS+N9wN2P0GNjy0upFgN35/CdYnjTAiEAqbQTGZTq1Kx6VAb6q6LNNosFX4BoT7M7sUsLMVQX0pc="}]},"_npmUser":{"name":"dominicprice","email":"dominicprice@outlook.com"},"directories":{},"maintainers":[{"name":"dominicprice","email":"dominicprice@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remotedata_1.0.0_1708378493178_0.8342923169655481"},"_hasShrinkwrap":false}},"time":{"created":"2024-02-19T21:34:53.041Z","1.0.0":"2024-02-19T21:34:53.333Z","modified":"2024-02-19T21:34:53.851Z"},"maintainers":[{"name":"dominicprice","email":"dominicprice@outlook.com"}],"description":"Remote Data library for typescript","homepage":"https://github.com/dominicprice/yard#readme","keywords":["remote","data","typescript"],"repository":{"type":"git","url":"git+https://github.com/dominicprice/yard.git"},"author":{"name":"Dominic Price"},"bugs":{"url":"https://github.com/dominicprice/yard/issues"},"license":"MIT","readme":"# @dominicprice/remotedata: Yet Another Remote Data Library\n\nJust another remote data library which does things how I like them.\n\n## Installation\n\nAvailable on npm:\n\n```sh\nnpm install @dominicprice/yard\n```\n\n## Basic Usage\n\nBasic usage revolves around the `RemoteData` interface and the `promise` and `fold` functions. Suppose you have some React component which fetches some data from an API, e.g.\n\n```jsx\nconst MyComponent = () => {\n  const [users, setUsers] = useState<User[]>([])\n  useEffect(() => {\n   client.getUsers().then(resp => setUsers(resp)); \n  }, [])\n  \n  return (\n    <table>\n        {users.map(user => <tr key={user.id}><td>{user.name}</td><td>{user.last_login}</td></tr>)}\n    </table>\n  );\n}\n```\n\nThis is fine, but there are some problems:\n* There is no feedback to the user while the data is being fetched\n* The page just appears to be blank if there is an error in the request\n\nWe can solve all of this by adding a flag and error (e.g. `userFetchStatus` `userFetchError`) to our state, but there are also problems with doing that:\n* We have to remember to check the flag each time (no IDE support)\n* If we store `null` as a default value, we have to type assert based on the flag's value\n\nRemoteData handles storing a flag and error value in a type-safe way:\n\n```jsx\nimport * as rd from \"@dominicprice/remotedata\";\n\nconst MyComponent = () => {\n  const [users, setUsers] = useState<rd.RemoteData<User>>(null);\n  useEffect(() => {\n    rd.promise(client.getUsers(), setUsers);\n  })\n  \n  return (\n    <table>\n      {rd.fold(users, {\n        success: (data) => data.map(user => <tr key={user.id}><td>{user.name}</td><td>{user.last_login}</td></tr>),\n        loading: () => <tr><td colSpan={2}>Loading...</td></tr>,\n        error: (err) => <tr><td colSpan={2}>Error fetching users: {err}</td></tr>,\n        notAsked: () => null,\n      })}\n    </table>\n  );\n}\n```\n\nThe `RemoteData` type can be in four different states:\n* `notAsked`: before any fetching has taken place, represented by a `null` value.\n* `loading`: while a promise is being resolved, has no extra data\n* `success`: after a promise is successfully resolved, contains an object of the specified type\n* `error`: after a promise rejects, contains an `Error` object\n\nThe `promise` function accepts a promise and a callback to assign the result of the promise to a `RemoteData` object. In React, this can just be a state setter. \n\nThe `fold` function accepts a remote data object and an object defining what to do in each of the four possible cases. All four cases must be defined, or if you only\ncare about a subset of the four cases you can use a `default` case to define fallback behaviour:\n\n```jsx\nrd.fold(users, {\n  success: data => <div>There are {data.length} users</div>\n  default: () => <div>There are no users</div>,\n})\n```\n\nThe `promise` function also accepts an additional third argument to define callbacks when the remote data reaches a different stage:\n* `onError: (err: Error) => void`: when the promise resolves to an error\n* `onSuccess: (value: T) => void`: when the promise resolves successfully\n* `onLoading: () => void`: when the promise enters the loading state\n\nFor example, to show a toast when an error occurs:\n\n```jsx\nrd.promise(client.getUsers(), setUsers, {\n  onError: (err) => displayErrorToast(err),\n})\n```\n\n\n## Additional uses\n\nThere are some other convenience functions provided:\n\n### `must`\n\nWhen you only care about the success state, you can use the `must` function which returns the successful value if the remote data is in the success state, or `undefined` otherwise. For example, if you have a component which some other logic means is only displayed when the remote data is in the success state, you can use\n\n```jsx\n<UserAvatar user={rd.must(user)!} />\n```\n\n### `derive`\n\nIf you have a component which only depends on a particular field of the fetched data, you can instantiate a `RemoteData` object for that field using the derive function:\n\n```jsx\nconst NameBadge = ({name}: {name: rd.RemoteData<string>}) => {\n  return <div>{rd.fold(name, {\n    success: name => name,\n    loading: () => \"Loading\",\n    error: () => \"Unknown\",\n    notAsked: () => \"\",\n  })}</div>;\n}\n\nconst MyComponent = ({userId}: {userId: string}) => {\n  const [user, setUser] = useState<rd.RemoteData<User>>(null);\n  \n  useEffect(() => {\n    rd.promise(client.getUser(userId), setUsers);\n  }, [userId]);\n  \n  return (\n    <div>\n      <h1>Welcome to your page</h1>\n      <NameBadge name={rd.derive(user, u => u.name)} />\n    </div>\n  );\n}\n```\n\nThis can also be used with the `always` and `never` constructors, which create a `RemoteData` object in the success and error states respectively.\n\n```jsx\n<NameBadge name={rd.always(\"Admin\")} />\n```\n","readmeFilename":"README.md"}