{"id":19418002,"url":"https://github.com/americanexpress/fetchye","last_synced_at":"2025-04-24T13:34:16.839Z","repository":{"id":39879995,"uuid":"290290721","full_name":"americanexpress/fetchye","owner":"americanexpress","description":"✨ If you know how to use Fetch, you know how to use Fetchye [fetch-yae]. Simple React Hooks, Centralized Cache, Infinitely Extensible.","archived":false,"fork":false,"pushed_at":"2024-11-25T14:34:59.000Z","size":1063,"stargazers_count":44,"open_issues_count":5,"forks_count":22,"subscribers_count":16,"default_branch":"main","last_synced_at":"2025-04-22T19:05:52.348Z","etag":null,"topics":["async","cache","data-fetching","fetch","one-app","promise","query","react","react-hooks","react-redux","redux","ssr"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/americanexpress.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-08-25T18:19:12.000Z","updated_at":"2025-01-03T14:17:26.000Z","dependencies_parsed_at":"2025-04-22T19:05:39.013Z","dependency_job_id":"1c88aaac-9886-48b3-80d5-22e44d0f73f2","html_url":"https://github.com/americanexpress/fetchye","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/americanexpress%2Ffetchye","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/americanexpress%2Ffetchye/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/americanexpress%2Ffetchye/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/americanexpress%2Ffetchye/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/americanexpress","download_url":"https://codeload.github.com/americanexpress/fetchye/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250636531,"owners_count":21463098,"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":["async","cache","data-fetching","fetch","one-app","promise","query","react","react-hooks","react-redux","redux","ssr"],"created_at":"2024-11-10T13:12:24.062Z","updated_at":"2025-04-24T13:34:16.798Z","avatar_url":"https://github.com/americanexpress.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/americanexpress/fetchye/raw/main/fetchye.png\" alt=\"Fetchye - One Amex\" width=\"50%\" /\u003e\n\u003c/h1\u003e\n\n\u003e If you know how to use Fetch, you know how to use Fetchye \\[fetch-yae\\]. Simple React Hooks, Centralized Cache, Infinitely Extensible.\n\n```js\n// ...\nimport { useFetchye } from 'fetchye';\n\nconst MyComponent = () =\u003e {\n  const { isLoading, data } = useFetchye('http://example.com/api/profile');\n  return (\n    !isLoading \u0026\u0026 (\n      \u003cp\u003e{data.body.name}\u003c/p\u003e\n    )\n  );\n};\n```\n\n## 📖 Table of Contents\n\n* [Features](#-features)\n* [Install \u0026 Setup](#%EF%B8%8F-install--setup)\n* [Usage](#-usage)\n* [API](#%EF%B8%8F-api)\n* [Mission](#-mission)\n\n## ✨ Features\n\n* ES6 Fetch powered by React Hooks\n* Pure React or Redux Shared Cache modes available\n* Headless per-Hook Cache Mode available\n* SSR-friendly\n\n## ⬇️ Install \u0026 Setup\n\n**Contents**\n\n* [Quick Install](#quick-install)\n* [FetchyeProvider Install](#fetchyeprovider-install)\n* [FetchyeReduxProvider Install](#fetchyereduxprovider-install)\n* [One App Install](#one-app-install)\n\n### Quick Install\n\n\u003e 💡 Makes use of Headless per-Hook Cache Mode\n\n**Pros**\n\n- Painless and Quick\n\n**Cons**\n\n- No shared caching\n- No de-duplication of API calls\n\nJust install and do `useFetchye`. Thats it!\n\n```sh\nnpm i -S fetchye\n```\n\n```js\n// ...\nimport { useFetchye } from 'fetchye';\n\nconst MyComponent = () =\u003e {\n  const { isLoading, data } = useFetchye('http://example.com/api/profile');\n  return (\n    !isLoading \u0026\u0026 (\n      \u003cp\u003e{data?.body.name}\u003c/p\u003e\n    )\n  );\n};\n```\n\n🏖️[Try this out on Codesandbox](https://codesandbox.io/s/americanexpressfetchye-quick-install-w4ne2)\n\n### `FetchyeProvider` Install\n\n\u003e 💡 When you want a central cache but no extra dependencies\n\n**Pros**\n\n- Easy\n- Shared Cache\n- De-duplication of API calls\n\n**Cons**\n\n- No Redux Dev Tools for debugging and cache inspection\n- Limited centralized server-side data hydration support\n\nInstall `fetchye`:\n\n```\nnpm i -S fetchye\n```\n\nAdd the `\u003cFetchyeProvider /\u003e` component:\n\n```jsx\nimport { FetchyeProvider } from 'fetchye';\n\nconst ParentComponent = ({ children }) =\u003e (\n  \u003cFetchyeProvider\u003e\n    {/* Use your Router to supply children components containing useFetchye */}\n    {children}\n  \u003c/FetchyeProvider\u003e\n);\n```\n\nIn a child React Component, do `useFetchye` queries:\n\n```js\n// ...\nimport { useFetchye } from 'fetchye';\n\nconst MyComponent = () =\u003e {\n  const { isLoading, data } = useFetchye('http://example.com/api/profile');\n  return (\n    !isLoading \u0026\u0026 (\n      \u003cp\u003e{data?.body.name}\u003c/p\u003e\n    )\n  );\n};\n```\n\n🏖️[Try this out on Codesandbox](https://codesandbox.io/s/americanexpressfetchye-fetchye-provider-install-y7d8j)\n\n### `FetchyeReduxProvider` Install\n\n\u003e 💡 When you want a central cache integrated with a Redux based project\n\n**Pros**\n\n- Easy if you know Redux\n- Shared Cache\n- De-duplication of API calls\n- Redux Dev Tools for debugging and cache inspection\n- Excellent centralized server-side data hydration support\n\n**Cons**\n\n- More steps and dependencies\n\nAdd `fetchye` and its needed optional dependencies:\n\n```\nnpm i -S fetchye redux react-redux\n```\n\nAdd the `\u003cFetchyeReduxProvider /\u003e` component under the Redux `\u003cProvider /\u003e`:\n\n```jsx\nimport React from 'react';\nimport { createStore } from 'redux';\nimport { Provider } from 'react-redux';\nimport { FetchyeReduxProvider } from 'fetchye-redux-provider';\nimport { SimpleCache } from 'fetchye';\n\nconst fetchyeCache = SimpleCache({\n  // Need to tell Fetchye where the cache reducer will be located\n  cacheSelector: (state) =\u003e state,\n});\nconst store = createStore(fetchyeCache.reducer);\n\nconst ParentComponent = ({ children }) =\u003e (\n  \u003cProvider store={store}\u003e\n    \u003cFetchyeReduxProvider cache={fetchyeCache}\u003e\n      {/* Use your Router to supply children components containing useFetchye */}\n      {children}\n    \u003c/FetchyeReduxProvider\u003e\n  \u003c/Provider\u003e\n);\n```\n\nIn a child React Component, do `useFetchye` queries:\n\n```js\n// ...\nimport { useFetchye } from 'fetchye';\n\nconst MyComponent = () =\u003e {\n  const { isLoading, data } = useFetchye('http://example.com/api/profile');\n  return (\n    !isLoading \u0026\u0026 (\n      \u003cp\u003e{data.body.name}\u003c/p\u003e\n    )\n  );\n};\n```\n\n🏖️[Try this out on Codesandbox](https://codesandbox.io/s/americanexpressfetchye-fetchye-redux-provider-install-4d2uz)\n\n### One App Install\n\n\u003e 💡 For when you use the [One App](https://github.com/americanexpress/one-app) Micro-Frontend Framework\n\n**Pros**\n\n- Shared Cache\n- De-duplication of API calls\n- Redux Dev Tools for debugging and cache inspection\n- Excellent centralized server-side data hydration support\n- Shared Cache between Micro Frontend Holocron Modules\n- Immutable Redux State\n- Minimal configuration\n\n**Cons**\n\n- More steps and dependencies\n\n```\nnpm i -S fetchye fetchye-one-app\n```\n\n`fetchye-one-app` provides pre-configured `provider`, `cache`, `oneFetchye` and `oneCacheSelector` to ensure that all modules use the same cache and reduce the chance for cache misses. These all have restricted APIs to reduce the chance for misconfiguration however if you require more control/customization use [`ImmutableCache`](#immutablecache), [`FetchyeReduxProvider`](#fetchyereduxprovider) and [`makeServerFetchye`](#makeserverfetchye). Please bear in mind that this can impact modules which are do not use the same configuration.\n\nAdd the `\u003cOneFetchyeProvider /\u003e` component from `fetchye-one-app` to your Root Holocron Module, and add the reducer from `OneCache` scoped under `fetchye`:\n\n```jsx\n// ...\nimport { combineReducers } from 'redux-immutable';\nimport { OneFetchyeProvider, OneCache } from 'fetchye-one-app';\n\nconst MyModuleRoot = ({ children }) =\u003e (\n  \u003c\u003e\n    { /* OneFetchyeProvider is configured to use OneCache */}\n    \u003cOneFetchyeProvider\u003e\n      {/* Use your Router to supply children components containing useFetchye */}\n      {children}\n    \u003c/OneFetchyeProvider\u003e\n  \u003c/\u003e\n);\n\n// ...\n\nMyModuleRoot.holocron = {\n  name: 'my-module-root',\n  reducer: combineReducers({\n    // ensure you scope the reducer under \"fetchye\", this is important\n    // to ensure that child modules can make use of the single cache\n    fetchye: OneCache().reducer,\n    // ... other reducers\n  }),\n};\n```\n\nIn a child React Component or Holocron Module, do `useFetchye` queries:\n\n```js\n// ...\nimport { useFetchye } from 'fetchye';\n\nconst MyComponent = () =\u003e {\n  const { isLoading, data } = useFetchye('http://example.com/api/profile');\n  return (\n    !isLoading \u0026\u0026 (\n      \u003cp\u003e{data?.body.name}\u003c/p\u003e\n    )\n  );\n};\n```\n\nThis minimal configuration works as the provider, cache and makeOneServerFetchye, mentioned later, all follow expected conventions.\n\n## 🤹‍ Usage\n\n### Real-World Example\n\n```jsx\nimport React from 'react';\nimport { useFetchye } from 'fetchye';\n\nconst BookList = ({ genre }) =\u003e {\n  const { isLoading, error, data } = useFetchye(`http://example.com/api/books/?genre=${genre}`, {\n    headers: {\n      'X-Some-Tracer-Id': 1234,\n    },\n  });\n\n  if (isLoading) {\n    return (\u003cp\u003eLoading...\u003c/p\u003e);\n  }\n\n  if (error || data.status !== 200) {\n    return (\u003cp\u003eOops!\u003c/p\u003e);\n  }\n\n  return (\n    \u003c\u003e\n      \u003ch1\u003eBooks by {genre}\u003c/h1\u003e\n      \u003cul\u003e\n        {data.body.map((book) =\u003e (\n          \u003cli key={book.id}\u003e{book.title} by {book.author}\u003c/li\u003e\n        ))}\n      \u003c/ul\u003e\n    \u003c/\u003e\n  );\n};\n```\n\n### Deferred execution\n\nWhen you need to delay execution of a `useFetchye` call, you may use\n`{ defer: true }` option. This is great for forms:\n\n```jsx\nimport React from 'react';\nimport { useFetchye } from 'fetchye';\n\nconst NewBookForm = () =\u003e {\n  const { formData, onChange } = useSomeFormHandler();\n  const { isLoading, run } = useFetchye('http://example.com/api/books', {\n    // include defer here\n    defer: true,\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify({\n      ...formData,\n    }),\n  });\n\n  const onSubmit = async (event) =\u003e {\n    event.preventDefault();\n    const { data, error } = await run();\n    // Check to make sure no error and data.status === 200 for success\n  };\n\n  return (\n    \u003cform onSubmit={onSubmit}\u003e\n      {/* ...form elements using onChange */}\n      {/* Hide Submit button when sending POST request */}\n      {!isLoading \u0026\u0026 \u003cbutton type=\"submit\"\u003eSubmit\u003c/button\u003e}\n    \u003c/form\u003e\n  );\n};\n```\n\n### Abort Inflight Requests\n\nWhen you neeed to abort the execution of requests inflight, passing a signal from the [Abort Controller](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) API to `useFetchye` as an option will enable this.\n\nConsidering `useFetchye` is a wrapper around fetch, passing a signal is the same and provides the same functionality as demonstrated below.\n\n```jsx\nimport React, { useEffect } from 'react';\nimport { useFetchye } from 'fetchye';\n\nconst AbortComponent = () =\u003e {\n  const controller = new AbortController();\n  useFetchye('http://example.com/api/books', { signal: controller.signal });\n\n  useEffect(() =\u003e () =\u003e controller.abort(), []);\n\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003eabortable component\u003c/h1\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\nInstead of setting up a `useEffect` within the component it's possible to pass a hook to signal using packages such as\n[use-unmount-signal](https://www.npmjs.com/package/use-unmount-signal/v/1.0.0).\n\n### Sequential API Execution\n\nPassing the 'isLoading' value from one useFetchye call to the 'defer' field of the next will prevent the second call from being made until the first has loaded.\n\nTo ensure the second api call is properly formed, you should also check that the data you expect from the first call exists:\n\n```jsx\nimport React from 'react';\nimport { useFetchye } from 'fetchye';\n\nconst MyFavoriteBook = () =\u003e {\n  const {\n    isLoading: loadingProfile,\n    error: profileError,\n    data: profile,\n  } = useFetchye('http://example.com/api/profile');\n\n  const profileHasBookId = !loadingProfile \u0026\u0026 profile?.body?.favoriteBookId;\n  const {\n    isLoading: loadingBook,\n    error: bookError,\n    data: favoriteBook,\n  } = useFetchye('http://example.com/api/books', {\n    defer: !profileHasBookId,\n    method: 'POST',\n    body: JSON.stringify({\n      bookId: profile?.body?.favoriteBookId,\n    }),\n  });\n\n  if (loadingProfile) {\n    return (\u003cp\u003eLoading Profile...\u003c/p\u003e);\n  }\n  if (profileError || profile.status !== 200) {\n    return (\u003cp\u003eOops!\u003c/p\u003e);\n  }\n  if (loadingBook) {\n    return (\u003cp\u003eLoading Favourite Book...\u003c/p\u003e);\n  }\n  if (bookError || favoriteBook.status !== 200) {\n    return (\u003cp\u003eOops!\u003c/p\u003e);\n  }\n\n  return (\n    favoriteBook.status === 200 \u0026\u0026 (\n      \u003c\u003e\n        \u003ch1\u003eMy Favorite Book\u003c/h1\u003e\n        \u003ch2\u003e{favoriteBook.body.title}\u003c/h2\u003e\n      \u003c/\u003e\n    )\n  );\n};\n```\n\nAlternatively, you can pass a function as the first parameter to useFetchye, if this function throws an exception, or returns a falsy value, the call will automatically be 'deferred' until the function does not throw.\n\nThis only works if the sequential data is passed to the second call in the url.\n\nIn this example, the function will throw `Cannot read properties of undefined` when trying to access 'favoriteBookId' in the non-existent body of the profile:\n\n```jsx\nimport React from 'react';\nimport { useFetchye } from 'fetchye';\n\nconst MyFavoriteBook = () =\u003e {\n  const {\n    isLoading: loadingProfile,\n    error: profileError,\n    data: profile,\n  } = useFetchye('http://example.com/api/profile');\n  const {\n    isLoading: loadingBook,\n    error: bookError,\n    data: favoriteBook,\n  } = useFetchye(() =\u003e `http://example.com/api/books/${profile.body.favoriteBookId}`);\n\n  if (loadingProfile) {\n    return (\u003cp\u003eLoading Profile...\u003c/p\u003e);\n  }\n  if (profileError || profile.status !== 200) {\n    return (\u003cp\u003eOops!\u003c/p\u003e);\n  }\n  if (loadingBook) {\n    return (\u003cp\u003eLoading Favourite Book...\u003c/p\u003e);\n  }\n  if (bookError || favoriteBook.status !== 200) {\n    return (\u003cp\u003eOops!\u003c/p\u003e);\n  }\n\n  return (\n    favoriteBook.status === 200 \u0026\u0026 (\n      \u003c\u003e\n        \u003ch1\u003eMy Favorite Book\u003c/h1\u003e\n        \u003ch2\u003e{favoriteBook.body.title}\u003c/h2\u003e\n      \u003c/\u003e\n    )\n  );\n};\n```\n\n### Refreshing\n\n```jsx\nimport React from 'react';\nimport { useFetchye } from 'fetchye';\n\nconst BookList = ({ genre }) =\u003e {\n  const {\n    isLoading,\n    data: booksData,\n    run,\n  } = useFetchye(`http://example.com/api/books/?genre=${genre}`);\n\n  if (isLoading) {\n    return (\u003cp\u003eLoading...\u003c/p\u003e);\n  }\n\n  return (\n    \u003c\u003e\n      {/* Render booksData */}\n      \u003cbutton type=\"button\" onClick={() =\u003e run()}\u003eRefresh\u003c/button\u003e\n    \u003c/\u003e\n  );\n};\n```\n\n### Custom Fetcher\n\nCustom fetchers allow for creating reusable data fetching logic for specific APIs or custom needs. They allow for a centrally provided\n`fetchClient` which wraps that client on a per `useFetchye` request basis.\n\n```jsx\nimport React from 'react';\nimport { useFetchye } from 'fetchye';\n\nconst graphqlFetcher = async (fetchClient, key, options) =\u003e {\n  let res;\n  let payload;\n  let error;\n  try {\n    res = await fetchClient('https://example.com/graphql', {\n      ...options,\n      method: 'POST',\n      headers: {\n        'X-Correlation-Id': 12345,\n        'Content-Type': 'application/json',\n      },\n      // The key contains the GraphQL object request rather than a URL in this case\n      body: JSON.stringify(key),\n    });\n    // GraphQL Response\n    const { data, errors } = await res.json();\n    // Pass through GraphQL Data\n    payload = {\n      data,\n      ok: res.ok,\n      status: res.status,\n    };\n    // Assign GraphQL errors to error\n    error = errors;\n  } catch (requestError) {\n    // eslint-disable-next-line no-console -- error useful to developer in specific error case\n    console.error(requestError);\n    error = requestError;\n  }\n  return {\n    payload,\n    error,\n  };\n};\n\nconst BookList = ({ genre }) =\u003e {\n  const { isLoading, data: booksData, run } = useFetchye({\n    query: `\n      query BookList($genre: Genre) {\n        book(genre: $genre) {\n          title\n          author\n        }\n      }\n      `,\n    variables: { genre },\n  }, {}, graphqlFetcher);\n\n  if (isLoading) {\n    return (\u003cp\u003eLoading...\u003c/p\u003e);\n  }\n\n  return (\n    \u003c\u003e\n      {/* Render booksData */}\n      \u003cbutton type=\"button\" onClick={() =\u003e run()}\u003eRefresh\u003c/button\u003e\n    \u003c/\u003e\n  );\n};\n```\n\n### Controlling the Cache Key\n\nBy passing mapKeyToCacheKey as an option you can customize the cacheKey without affecting the key. This allows you to control the cacheKey directly to enable advanced behaviour in your cache.\n\nNote: This option can lead to unexpected behaviour in many cases. Customizing the cacheKey in this way could lead to accidental collisions that lead to fetchye providing the 'wrong' cache for some of your calls, or unnecessary cache-misses causing significant performance degradation.\n\nIn this example the client can dynamically switch between http and https depending on the needs of the user, but should keep the same cache key.\n\nTherefore, mapKeyToCacheKey is defined to transform the url to always have the same protocol in the cacheKey.\n\n```jsx\nimport React from 'react';\nimport { useFetchye } from 'fetchye';\n\nconst BookList = ({ ssl }) =\u003e {\n  const { isLoading, data } = useFetchye(`${ssl ? 'https' : 'http'}://example.com/api/books/`,\n    {\n      mapKeyToCacheKey: (key) =\u003e key.replace('https://', 'http://'),\n    }\n  );\n\n  if (isLoading) {\n    return (\u003cp\u003eLoading...\u003c/p\u003e);\n  }\n\n  return (\n    {/* Render data */ }\n  );\n};\n```\n\n### Passing dynamic headers\n\nWhen you call the `run` function returned from useFetchye, it will use the values last rendered into the hook.\n\nThis means any correlationId, timestamp, or any other unique dynamic header you might want sent to the server will use its previous value.\n\nTo overcome this, you can specify a function instead of a `headers` object in the options.\n\nThis function will be called, to re-make the headers just before an API call is made, even when you call `run`.\n\nNote: If you don't want the dynamic headers to result in a cache miss, you must remove the keys of the dynamic headers from the options using `mapOptionsToKey` (see example below that uses the `ignoreHeadersByKey` helper).\n\n```jsx\nimport React from 'react';\nimport { useFetchye, ignoreHeadersByKey } from 'fetchye';\nimport uuid from 'uuid';\n\nconst BookList = () =\u003e {\n  const { isLoading, data } = useFetchye('http://example.com/api/books/', {\n    // remove the 'correlationId' header from the headers, as its the only dynamic header\n    mapOptionsToKey: ignoreHeadersByKey(['correlationId']),\n    headers: () =\u003e ({\n      // static headers are still fine, and can be specified here like normal\n      staticHeader: 'staticValue',\n      // This header will be generated fresh for every call out of the system\n      correlationId: uuid(),\n    }),\n  });\n\n  if (isLoading) {\n    return (\u003cp\u003eLoading...\u003c/p\u003e);\n  }\n\n  return (\n    {/* Render data */ }\n  );\n};\n\nexport default BookList;\n```\n\n### SSR\n\n#### One App SSR\n\nUsing `oneFetchye` from `fetchye-one-app` ensures that the cache will always be configured correctly.\n\n```jsx\nimport React from 'react';\nimport { useFetchye } from 'fetchye';\nimport { oneFetchye } from 'fetchye-one-app';\n\nconst BookList = () =\u003e {\n  const { isLoading, data } = useFetchye('http://example.com/api/books/');\n\n  if (isLoading) {\n    return (\u003cp\u003eLoading...\u003c/p\u003e);\n  }\n\n  return (\n    {/* Render data */ }\n  );\n};\n\nBookList.holocron = {\n  loadModuleData: async ({ store: { dispatch } }) =\u003e {\n    if (global.BROWSER) {\n      return;\n    }\n\n    // oneFetchye has same arguments as useFetchye\n    // dispatches events into the server side Redux store\n    await dispatch(oneFetchye('http://example.com/api/books/'));\n  },\n};\n\nexport default BookList;\n```\n\n#### Next.JS SSR\n\n```jsx\nimport { useFetchye, makeServerFetchye, SimpleCache } from 'fetchye';\n\nconst cache = SimpleCache();\n\n// Codesandbox takes a second to get Next.JS started...\nexport default function IndexPage({ initialBookList }) {\n  const { isLoading, data } = useFetchye('http://example.com/api/books/', {\n    initialData: initialBookList,\n  });\n\n  if (isLoading) {\n    return (\u003cp\u003eLoading...\u003c/p\u003e);\n  }\n\n  return (\n    {/* Render data */ }\n  );\n}\n\nconst fetchye = makeServerFetchye({\n  cache,\n  fetchClient: fetch,\n});\n\nexport async function getServerSideProps() {\n  try {\n    // returns { data, error } payload for feeding initialData on client side\n    const res = await fetchye('http://example.com/api/books/');\n    return {\n      props: {\n        initialBookList: res,\n      },\n    };\n  } catch (error) {\n    // eslint-disable-next-line no-console -- error useful to developer in specific error case\n    console.error(error.message);\n    return {};\n  }\n}\n```\n\n🏖️[Try this out on Codesandbox](https://codesandbox.io/s/americanexpressfetchye-fetchye-ssr-0ktx9)\n\n## Write your own Cache\n\n\u003e 💬 **Note\n**: This is for advanced users with special cases. Advanced users should understand Redux design pattern concepts about [Reducers](https://redux.js.org/basics/reducers) and [Actions](https://redux.js.org/basics/actions) before continuing.\n\nSometimes, the basic opinions of the cache may not be enough for a project's use case. We can create a very basic new Cache configuration like so:\n\n```js\nimport {\n  IS_LOADING,\n  SET_DATA,\n  DELETE_DATA,\n  ERROR,\n  CLEAR_ERROR,\n} from 'fetchye';\n\nexport function CustomCache({ cacheSelector = (state) =\u003e state }) {\n  return {\n    // The reducer will save each action to state by hash key\n    reducer: (state, action) =\u003e {\n      switch (action.type) {\n        case IS_LOADING: {\n          // return is loading state change\n          return state;\n        }\n        case SET_DATA: {\n          // return set data state change\n          return state;\n        }\n        case DELETE_DATA: {\n          // return delete data state change\n          return state;\n        }\n        case ERROR: {\n          // return error state change\n          return state;\n        }\n        case CLEAR_ERROR: {\n          // return clear error state change\n          return state;\n        }\n        default: {\n          return state;\n        }\n      }\n    },\n    getCacheByKey: (state, key) =\u003e ({\n      data, // dig into state and return data by key hash value\n      error, // dig into state and return error by key hash value\n      loading, // dig into state and return loading by key hash value\n    }),\n    cacheSelector, // pass through optional cacheSelector property\n  };\n}\n```\n\nNext we may add this to one of the Fetchye Providers and we are done:\n\n```jsx\nimport { FetchyeProvider } from 'fetchye';\nimport { CustomCache } from './CustomCache';\n\nconst ParentComponent = ({ children }) =\u003e (\n  \u003cFetchyeProvider cache={CustomCache()}\u003e\n    {children}\n  \u003c/FetchyeProvider\u003e\n);\n```\n\n\u003e 💡 Check out [Actions API docs](#actions) and [`SimpleCache.js`](./src/cache/SimpleCache.js) source file. These will give you insights into the actions used in the reducer and practical examples on a working Cache configuration.\n\n## 🎛️ API\n\n**Contents**\n\n* [`useFetchye`](#usefetchye)\n* [`makeServerFetchye`](#makeserverfetchye)\n* [`makeOneServerFetchye`](#makeoneserverfetchye) (deprecated)\n* [`oneFetchye`](#oneFetchye)\n* [Providers](#providers)\n  * [`FetchyeProvider`](#fetchyeprovider)\n  * [`FetchyeReduxProvider`](#fetchyereduxprovider)\n  * [`OneFetchyeProvider`](#oneFetchyeProvider)\n* [Caches](#caches)\n  * [`SimpleCache`](#simplecache)\n  * [`ImmutableCache`](#immutablecache)\n  * [`OneCache`](#onecache)\n* [Actions](#actions)\n  * [`IS_LOADING`](#is_loading)\n  * [`SET_DATA`](#set_data)\n  * [`DELETE_DATA`](#delete_data)\n  * [`ERROR`](#error)\n  * [`CLEAR_ERROR`](#clear_error)\n* [`mapOptionToKey Helpers`](#mapoptiontokey-helpers)\n  * [`ignoreHeadersByKey`](#ignoreheadersbykey)\n\n### `useFetchye`\n\nA React Hook used for dispatching asynchronous API requests.\n\n**Shape**\n\n```\nconst { isLoading, data, error, run } = useFetchye(key, { defer: Boolean, mapOptionsToKey: options =\u003e options, ...fetchOptions }, fetcher);\n```\n\n**Arguments**\n\n| name      | type                                                                                                 | required | description                                                                                                                                        |\n|-----------|------------------------------------------------------------------------------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------|\n| `key`     | `String` or `() =\u003e String`                                                                           | `true`   | A string or function returning a string that factors into cache key creation. *Defaults to URL compatible string*.                                 |\n| `options` | `Object\u003cOptions\u003e`                                                                                    | `false`  | Options to pass through to ES6 Fetch. See **Options** table for the exceptions to this rule. The `options` object factors into cache key creation. |\n| `fetcher` | `async (fetchClient: Fetch, key: String, options: Options) =\u003e ({ payload: Object, error?: Object })` | `false`  | The async function that calls `fetchClient` by key and options. Returns a `payload` with outcome of `fetchClient` and an optional `error` object.  |\n\n**Options**\n\n| name               | type                                                  | required | description                                                                                                                                                         |\n|--------------------|-------------------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `mapOptionsToKey`  | `(options: Options) =\u003e transformedOptions`            | `false`  | A function that maps options to the key that will become part of the cache key. See below for a list of mapOptionsToKey helpers.                                    |\n| `mapKeyToCacheKey` | `(key: String, options: Options) =\u003e cacheKey: String` | `false`  | A function that maps the key for use as the cacheKey allowing direct control of the cacheKey                                                                        |\n| `defer`            | `Boolean`                                             | `false`  | Prevents execution of `useFetchye` on each render in favor of using the returned `run` function. *Defaults to `false`*                                              |\n| `initialData`      | `Object`                                              | `false`  | Seeds the initial data on first render of `useFetchye` to accomodate server side rendering *Defaults to `undefined`*                                                |\n| `headers`          | `Object` or `() =\u003e Object`                            | `false`  | `Object`: as per the ES6 Compatible `fetch` option. `() =\u003e Object`: A function to construct a ES6 Compatible `headers` object prior to any api call                 |\n| `...restOptions`   | `ES6FetchOptions`                                     | `true`   | Contains any ES6 Compatible `fetch` option. (See [Fetch Options](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Supplying_request_options)) |\n\n**Returns**\n\n| name        | type             | description                                                                                                                                                                     |\n|-------------|------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `isLoading` | `Boolean`        | A boolean to indicate whether in loading state or not.                                                                                                                          |\n| `data`      | `Object`         | A result of a `fetchClient` query. *Defaults to returning `{ status, body, ok, headers }` from `fetchClient` response*                                                          |\n| `error?`    | `Object`         | An object containing an error if present. *Defaults to an `Error` object with a thrown `fetch` error. This is not for API errors (e.g. Status 500 or 400). See `data` for that* |\n| `run`       | `async () =\u003e {}` | A function for bypassing the cache and firing an API call. This will cause `isLoading === true` and update the cache based on the result.                                       |\n\n### `makeServerFetchye`\n\nA factory function used to generate an async/await fetchye function used for server-side API calls.\n\n**Shape**\n\n```\nconst fetchye = makeServerFetchye({ cache, fetchClient });\n\nconst { data, error } = await fetchye(key, options, fetcher);\n```\n\n**`makeServerFetchye` Arguments**\n\n| name          | type       | required | description                                                                                    |\n|---------------|------------|----------|------------------------------------------------------------------------------------------------|\n| `cache`       | `Cache`    | `true`   | Fetchye `Cache` object.                                                                        |\n| `fetchClient` | `ES6Fetch` | `true`   | A [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) compatible function. |\n\n**`fetchye` Arguments**\n\n| name      | type                                                                                                 | required | description                                                                                                                                       |\n|-----------|------------------------------------------------------------------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------|\n| `key`     | `String` or `() =\u003e String`                                                                           | `true`   | A string or function returning a string that factors into cache key creation. *Defaults to URL compatible string*.                                |\n| `options` | `ES6FetchOptions`                                                                                    | `false`  | Options to pass through to [ES6 Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).                                               |\n| `fetcher` | `async (fetchClient: Fetch, key: String, options: Options) =\u003e ({ payload: Object, error?: Object })` | `false`  | The async function that calls `fetchClient` by key and options. Returns a `payload` with outcome of `fetchClient` and an optional `error` object. |\n\n**`fetchye` Returns**\n\n| name     | type             | description                                                                                                                                                                     |\n|----------|------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `data`   | `Object`         | A result of a `fetchClient` query. *Defaults to returning `{ status, body, ok, headers }` from `fetchClient` response*                                                          |\n| `error?` | `Object`         | An object containing an error if present. *Defaults to an `Error` object with a thrown `fetch` error. This is not for API errors (e.g. Status 500 or 400). See `data` for that* |\n| `run`    | `async () =\u003e {}` | A function for bypassing the cache and firing an API call. Can be awaited.                                                                                                      |\n\n### `makeOneServerFetchye`\n\nDEPRECATED: You should use `dispatch(oneFetchye(key, options, fetcher))` (see docs below) in place of `makeOneServerFetchye`\n\nA factory function used to generate an async/await fetchye function used for making One App server-side API calls.\n\n**Shape**\n\n```\nconst fetchye = makeOneServerFetchye({ store, fetchClient });\n\nconst { data, error } = await fetchye(key, options, fetcher);\n```\n\n**`makeOneServerFetchye` Arguments**\n\n| name          | type       | required | description                                                                                    |\n|---------------|------------|----------|------------------------------------------------------------------------------------------------|\n| `cache`       | `Cache`    | `false`  | *Defaults to OneCache* Fetchye `Cache` object.                                                 |\n| `fetchClient` | `ES6Fetch` | `true`   | A [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) compatible function. |\n| `store`       | `Store`    | `true`   | A [Redux Store](https://redux.js.org/api/store)                                                |\n\n**`fetchye` Arguments**\n\n| name      | type                                                                                                 | required | description                                                                                                                                       |\n|-----------|------------------------------------------------------------------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------|\n| `key`     | `String` or `() =\u003e String`                                                                           | `true`   | A string or function returning a string that factors into cache key creation. *Defaults to URL compatible string*.                                |\n| `options` | `ES6FetchOptions`                                                                                    | `false`  | Options to pass through to [ES6 Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).                                               |\n| `fetcher` | `async (fetchClient: Fetch, key: String, options: Options) =\u003e ({ payload: Object, error?: Object })` | `false`  | The async function that calls `fetchClient` by key and options. Returns a `payload` with outcome of `fetchClient` and an optional `error` object. |\n\n**`fetchye` Returns**\n\n| name     | type             | description                                                                                                                                                                     |\n|----------|------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `data`   | `Object`         | A result of a `fetchClient` query. *Defaults to returning `{ status, body, ok, headers }` from `fetchClient` response*                                                          |\n| `error?` | `Object`         | An object containing an error if present. *Defaults to an `Error` object with a thrown `fetch` error. This is not for API errors (e.g. Status 500 or 400). See `data` for that* |\n| `run`    | `async () =\u003e {}` | A function for bypassing the cache and firing an API call. Can be awaited.                                                                                                      |\n\n### oneFetchye\n\nCall fetchye in an imperative context, such as in One App's loadModuleData, in a Redux Thunk, or in an useEffect.\n\n**Shape**\n\n```\nconst { data, error } = await dispatch(oneFetchye(key, options, fetcher));\n```\n\n**`oneFetchye` Arguments**\n\n| name      | type                                                                                                 | required | description                                                                                                                                       |\n|-----------|------------------------------------------------------------------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------|\n| `key`     | `String` or `() =\u003e String`                                                                           | `true`   | A string or function returning a string that factors into cache key creation. *Defaults to URL compatible string*.                                |\n| `options` | `ES6FetchOptions`                                                                                    | `false`  | Options to pass through to [ES6 Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).                                               |\n| `fetcher` | `async (fetchClient: Fetch, key: String, options: Options) =\u003e ({ payload: Object, error?: Object })` | `false`  | The async function that calls `fetchClient` by key and options. Returns a `payload` with outcome of `fetchClient` and an optional `error` object. |\n\n**`onefetchye` Returns**\n\nA promise resolving to an object with the below keys:\n\n| name     | type             | description                                                                                                                                                                     |\n|----------|------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `data`   | `Object`         | A result of a `fetchClient` query. *Defaults to returning `{ status, body, ok, headers }` from `fetchClient` response*                                                          |\n| `error?` | `Object`         | An object containing an error if present. *Defaults to an `Error` object with a thrown `fetch` error. This is not for API errors (e.g. Status 500 or 400). See `data` for that* |\n| `run`    | `async () =\u003e {}` | A function for bypassing the cache and firing an API call. Can be awaited.                                                                                                      |\n\n### Providers\n\nA Provider creates a React Context to connect all the `useFetchye` Hooks into a centrally stored cache.\n\n#### `FetchyeProvider`\n\nA React Context Provider that holds the centralized cache for all the `useFetchye` React Hooks' query data. This Provider uses `useReducer` for cache storage.\n\n**Shape**\n\n```\n\u003cFetchyeProvider cache={SimpleCache()}\u003e\n  {children}\n\u003c/FetchyeProvider\u003e\n```\n\n**Props**\n\n| name          | type       | required | description                                                                                    |\n|---------------|------------|----------|------------------------------------------------------------------------------------------------|\n| `fetchClient` | `ES6Fetch` | `true`   | A [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) compatible function. |\n| `cache`       | `Cache`    | `false`  | Fetchye `Cache` object. *Defaults to `SimpleCache`*                                            |\n| `initialData` | `Object`   | `false`  | Initial state to feed into Cache Configuration `reducer`                                       |\n\n#### `FetchyeReduxProvider`\n\n\u003e 💡Requires additional `redux` and `react-redux` packages installed\n\nA React Context Provider that uses Redux to store the centralized cache for all the `useFetchye` React Hooks' query data.\n\n**Shape**\n\n```\nimport { FetchyeReduxProvider } from \"fetchye-redux-provider\";\n```\n\n```\n\u003cProvider\u003e\n  \u003cFetchyeReduxProvider cache={SimpleCache()}\u003e\n    {children}\n  \u003c/FetchyeReduxProvider\u003e\n\u003c/Provider\u003e\n```\n\n**Context**\n\n| name                | type                | required | description                                                                       |\n|---------------------|---------------------|----------|-----------------------------------------------------------------------------------|\n| `ReactReduxContext` | `ReactReduxContext` | `true`   | A [Redux Context](https://react-redux.js.org/api/provider) from a `\u003cProvider /\u003e`. |\n\n**Props**\n\n| name          | type       | required | description                                                                                    |\n|---------------|------------|----------|------------------------------------------------------------------------------------------------|\n| `fetchClient` | `ES6Fetch` | `true`   | A [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) compatible function. |\n| `cache`       | `Cache`    | `false`  | Fetchye `Cache` object. *Defaults to `SimpleCache`*                                            |\n\n#### `OneFetchyeProvider`\n\n\u003e 💡Requires additional `redux` and `react-redux` packages installed\n\nA Context Provider that is specifically designed for use with One App.\n\n**Shape**\n\n```js\nimport { OneFetchyeProvider } from 'fetchye-one-app';\n```\n\n```js\n\u003cProvider\u003e\n  \u003cOneFetchyeProvider\u003e\n    {children}\n  \u003c/OneFetchyeProvider\u003e\n\u003c/Provider\u003e;\n```\n\n**Context**\n\n| name                | type                | required | description                                                                       |\n|---------------------|---------------------|----------|-----------------------------------------------------------------------------------|\n| `ReactReduxContext` | `ReactReduxContext` | `true`   | A [Redux Context](https://react-redux.js.org/api/provider) from a `\u003cProvider /\u003e`. |\n\n**Props**\n\n| name          | type       | required | description                                                                                    |\n|---------------|------------|----------|------------------------------------------------------------------------------------------------|\n| `fetchClient` | `ES6Fetch` | `true`   | A [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) compatible function. |\n| `cache`       | `Cache`    | `false`  | Fetchye `Cache` object. *Defaults to `OneCache`*                                               |\n\n### Caches\n\nA factory function that returns a configuration object, used to instruct a Provider on how to store and retrieve fetchye cache data.\n\n#### `SimpleCache`\n\nThis Cache configuration relies on plain old Javascript data structures to back the `reducer` and `getCacheByKey` functions.\n\n**Shape**\n\n```\nimport { SimpleCache } from 'fetchye';\n\nconst cache = SimpleCache({\n  cacheSelector,\n});\n```\n\n**Arguments**\n\n| name            | type               | required | description                                                                                                                                                                                            |\n|-----------------|--------------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `cacheSelector` | `(state) =\u003e state` | `false`  | *Required if using `FetchyeReduxProvider`* A function that returns the location inside Redux State to the Fetchye Cache. (See [Redux Selectors](https://redux.js.org/recipes/computing-derived-data)). |\n\n**Returns**\n\n| name             | type                       | description                                                                                                                                                                                 |\n|------------------|----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `reducer`        | `(state, action) =\u003e state` | A function that reduces the next state of Fetchye Cache. (See [Redux Reducers](https://redux.js.org/basics/reducers)).                                                                      |\n| `getCacheByKey`  | `(cache, key) =\u003e state`    | A function that returns a minimum of `{ data, loading, error }` for a specific cache key from cache state.                                                                                  |\n| `cacheSelector?` | `(state) =\u003e state`         | An optionally returned parameter. This function returns the location inside Redux State to the Fetchye Cache. (See [Redux Selectors](https://redux.js.org/recipes/computing-derived-data)). |\n\n#### `ImmutableCache`\n\n\u003e 💡Requires additional `immutable` package installed\n\nThis Cache configuration relies on ImmutableJS data structures to back the `reducer` and `getCacheByKey` functions.\n\n**Shape**\n\n```\nimport { ImmutableCache } from 'fetchye-immutable-cache';\n\nconst cache = ImmutableCache({\n  cacheSelector\n});\n```\n\n**Arguments**\n\n| name            | type               | required | description                                                                                                                                                                                            |\n|-----------------|--------------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `cacheSelector` | `(state) =\u003e state` | `false`  | *Required if using `FetchyeReduxProvider`* A function that returns the location inside Redux State to the Fetchye Cache. (See [Redux Selectors](https://redux.js.org/recipes/computing-derived-data)). |\n\n**Returns**\n\n| name             | type                                      | description                                                                                                                                                                                 |\n|------------------|-------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `reducer`        | `(state, action) =\u003e state`                | A function that reduces the next state of Fetchye Cache. (See [Redux Reducers](https://redux.js.org/basics/reducers)).                                                                      |\n| `getCacheByKey`  | `(cache = Immutable.Map(), key) =\u003e state` | A function that returns a minimum of `{ data, loading, error }` for a specific cache key from cache state.                                                                                  |\n| `cacheSelector?` | `(state) =\u003e state`                        | An optionally returned parameter. This function returns the location inside Redux State to the Fetchye Cache. (See [Redux Selectors](https://redux.js.org/recipes/computing-derived-data)). |\n\n#### `OneCache`\n\n\u003e 💡Requires additional `immutable` package installed\n\nThis Cache configuration is specifically designed to work with One App, it relies on ImmutableJS data structures to back the `reducer` and `getCacheByKey` functions.\n\n**Shape**\n\n```\nimport { OneCache } from 'fetchye-one-app';\n\nconst cache = OneCache();\n```\n\n**Returns**\n\n| name             | type                                      | description                                                                                                                                                                                 |\n|------------------|-------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `reducer`        | `(state, action) =\u003e state`                | A function that reduces the next state of Fetchye Cache. (See [Redux Reducers](https://redux.js.org/basics/reducers)).                                                                      |\n| `getCacheByKey`  | `(cache = Immutable.Map(), key) =\u003e state` | A function that returns a minimum of `{ data, loading, error }` for a specific cache key from cache state.                                                                                  |\n| `cacheSelector?` | `(state) =\u003e state`                        | An optionally returned parameter. This function returns the location inside Redux State to the Fetchye Cache. (See [Redux Selectors](https://redux.js.org/recipes/computing-derived-data)). |\n\n### Actions\n\nThese actions power the state transitions described in a Cache Configuration `reducer` function.\n\n#### `IS_LOADING`\n\nAn event signaling a state transition to the loading state by hash key.\n\n**Shape**\n\n```\nimport { IS_LOADING } from 'fetchye-core';\n```\n\n```\n{\n  type: IS_LOADING,\n  hash,\n}\n```\n\n**Child Properties**\n\n| name   | type     | description                                                                                              |\n|--------|----------|----------------------------------------------------------------------------------------------------------|\n| `hash` | `String` | The hash value generated by [`object-hash`](https://github.com/puleos/object-hash) package for the query |\n\n#### `SET_DATA`\n\nAn event signaling a state transition inside a reducer to add or replace the data field and transition away from loading state by hash key.\n\n**Shape**\n\n```\nimport { SET_DATA } from 'fetchye-core';\n```\n\n```\n{\n  type: SET_DATA,\n  hash,\n  value,\n}\n```\n\n**Child Properties**\n\n| name    | type     | description                                                                                              |\n|---------|----------|----------------------------------------------------------------------------------------------------------|\n| `hash`  | `String` | The hash value generated by [`object-hash`](https://github.com/puleos/object-hash) package for the query |\n| `value` | `Object` | Contains the `payload` data returned from the `fetcher` inside `useFetchye`                              |\n\n#### `DELETE_DATA`\n\nAn event signaling a state transition inside a reducer to remove the data field by hash key.\n\n**Shape**\n\n```\nimport { DELETE_DATA } from 'fetchye-core';\n```\n\n```\n{\n  type: DELETE_DATA,\n  hash,\n}\n```\n\n**Child Properties**\n\n| name   | type     | description                                                                                              |\n|--------|----------|----------------------------------------------------------------------------------------------------------|\n| `hash` | `String` | The hash value generated by [`object-hash`](https://github.com/puleos/object-hash) package for the query |\n\n#### `ERROR`\n\nAn event signaling a state transition inside a reducer to insert an error and transition away from loading state by hash key.\n\n**Shape**\n\n```\nimport { ERROR } from 'fetchye-core';\n```\n\n```\n{\n  type: ERROR,\n  hash,\n  error,\n}\n```\n\n**Child Properties**\n\n| name    | type     | description                                                                                              |\n|---------|----------|----------------------------------------------------------------------------------------------------------|\n| `hash`  | `String` | The hash value generated by [`object-hash`](https://github.com/puleos/object-hash) package for the query |\n| `error` | `Error   | String                                                                                                   | null` | Contains the `error` value returned from the `fetcher` inside `useFetchye` |\n\n#### `CLEAR_ERROR`\n\nAn event signaling a state transition inside a reducer to remove an error by hash key.\n\n**Shape**\n\n```\nimport { CLEAR_ERROR } from 'fetchye-core';\n```\n\n```\n{\n  type: CLEAR_ERROR,\n  hash,\n}\n```\n\n**Child Properties**\n\n| name   | type     | description                                                                                              |\n|--------|----------|----------------------------------------------------------------------------------------------------------|\n| `hash` | `String` | The hash value generated by [`object-hash`](https://github.com/puleos/object-hash) package for the query |\n\n### mapOptionToKey Helpers\n\nThese helpers provide a more compact and simple way of common transforms.\n\nThere is currently one helper.\n\n#### ignoreHeadersByKey\n\n**Shape**\n\n`(String[]) =\u003e mapOptionsToKeyFunction`\n\n**Arguments**\n\n| name   | type            | required | description                                                                                 |\n|--------|-----------------|----------|---------------------------------------------------------------------------------------------|\n| `keys` | `Array\u003cString\u003e` | `true`   | creates a mapOptionsToKey function that removes headers whose keys match the specified keys |\n\n**Returns**\n\n| name                       | type                      | description                                                                                                                 |\n|----------------------------|---------------------------|-----------------------------------------------------------------------------------------------------------------------------|\n| `mapOptionsToKey Function` | `mapOptionsToKeyFunction` | A function to be passed to the mapOptionsToKey option in useFetchye, or the `fetchye` function made by `makeServerFetchye`. |\n\n**Example**\n\n```jsx\nimport React from 'react';\nimport { useFetchye, ignoreHeadersByKey } from 'fetchye';\n\nconst BookList = ({ locale }) =\u003e {\n  const { isLoading, data } = useFetchye('http://example.com/api/books/', {\n    // remove the 'locale' header from the headers when building the cache key\n    mapOptionsToKey: ignoreHeadersByKey(['locale']),\n    headers: { locale },\n  });\n\n  // ... rest of component\n};\n\nexport default BookList;\n```\n\n## 📢 Mission\n\nThe Fetchye project wishes to bring a more flexible central caching experience using the best ideas of the Redux design pattern and options for the developer to choose how their data is stored. Fetchye provides React Context driven caching options backed by your choice of pure React (via `useReducer`) or Redux. Unlike many data fetching solutions, Fetchye Context Providers do not rely on singleton statics and can be instantiated throughout an application multiple times for multiple caches if so desired.\n\n## 🏆 Contributing\n\nWe welcome Your interest in the American Express Open Source Community on Github. Any Contributor to any Open Source Project managed by the American Express Open Source Community must accept and sign an Agreement indicating agreement to the terms below. Except for the rights granted in this Agreement to American Express and to recipients of software distributed by American Express, You reserve all right, title, and interest, if any, in and to Your Contributions. Please [fill out the Agreement](https://cla-assistant.io/americanexpress/fetchye).\n\nPlease feel free to open pull requests and see [CONTRIBUTING.md](./CONTRIBUTING.md) to learn how to get started contributing.\n\n## 🗝️ License\n\nAny contributions made under this project will be governed by the [Apache License 2.0](./LICENSE.txt).\n\n## 🗣️ Code of Conduct\n\nThis project adheres to the [American Express Community Guidelines](./CODE_OF_CONDUCT.md). By participating, you are expected to honor these guidelines.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famericanexpress%2Ffetchye","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famericanexpress%2Ffetchye","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famericanexpress%2Ffetchye/lists"}