Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(oneFetchye): make even cleaner api for fetchtye #90

Merged
merged 2 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 42 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
npm i -S fetchye fetchye-one-app
```

`fetchye-one-app` provides pre-configured `provider`, `cache`, `makeOneServerFetchye`
`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.
Expand Down Expand Up @@ -350,7 +350,7 @@
const controller = new AbortController();
useFetchye('http://example.com/api/books', { signal: controller.signal });

useEffect(() => () => controller.abort(), []);

Check warning on line 353 in README.md

View workflow job for this annotation

GitHub Actions / Node 12.x

React Hook useEffect has a missing dependency: 'controller'. Either include it or remove the dependency array

Check warning on line 353 in README.md

View workflow job for this annotation

GitHub Actions / Node 14.x

React Hook useEffect has a missing dependency: 'controller'. Either include it or remove the dependency array

Check warning on line 353 in README.md

View workflow job for this annotation

GitHub Actions / Node 16.x

React Hook useEffect has a missing dependency: 'controller'. Either include it or remove the dependency array

Check warning on line 353 in README.md

View workflow job for this annotation

GitHub Actions / Node 18.x

React Hook useEffect has a missing dependency: 'controller'. Either include it or remove the dependency array

return (
<div>
Expand Down Expand Up @@ -633,13 +633,13 @@

#### One App SSR

Using `makeOneServerFetchye` from `fetchye-one-app` ensures that the cache will
Using `oneFetchye` from `fetchye-one-app` ensures that the cache will
always be configured correctly.

```jsx
import React from 'react';
import { useFetchye } from 'fetchye';
import { makeOneServerFetchye } from 'fetchye-one-app';
import { oneFetchye } from 'fetchye-one-app';

const BookList = () => {
const { isLoading, data } = useFetchye('http://example.com/api/books/');
Expand All @@ -654,19 +654,14 @@
};

BookList.holocron = {
loadModuleData: async ({ store: { dispatch, getState }, fetchClient }) => {
loadModuleData: async ({ store: { dispatch } }) => {
if (global.BROWSER) {
return;
}
const fetchye = makeOneServerFetchye({
// Redux store
store: { dispatch, getState },
fetchClient,
});

// async/await fetchye has same arguments as useFetchye
// oneFetchye has same arguments as useFetchye
// dispatches events into the server side Redux store
await fetchye('http://example.com/api/books/');
await dispatch(oneFetchye('http://example.com/api/books/'));
},
};

Expand Down Expand Up @@ -795,12 +790,16 @@

* [`useFetchye`](#usefetchye)
* [`makeServerFetchye`](#makeserverfetchye)
* [`makeOneServerFetchye`](#makeoneserverfetchye) (deprecated)
* [`oneFetchye`](#oneFetchye)
* [Providers](#providers)
* [`FetchyeProvider`](#fetchyeprovider)
* [`FetchyeReduxProvider`](#fetchyereduxprovider)
* [`OneFetchyeProvider`](#oneFetchyeProvider)
* [Caches](#caches)
* [`SimpleCache`](#simplecache)
* [`ImmutableCache`](#immutablecache)
* [`OneCache`](#onecache)
* [Actions](#actions)
* [`IS_LOADING`](#is_loading)
* [`SET_DATA`](#set_data)
Expand Down Expand Up @@ -885,6 +884,8 @@

### `makeOneServerFetchye`

DEPRECATED: You should use `dispatch(oneFetchye(key, options, fetcher))` (see docs below) in place of `makeOneServerFetchye`

A factory function used to generate an async/await fetchye function used for making One App server-side API calls.

**Shape**
Expand All @@ -895,13 +896,13 @@
const { data, error } = await fetchye(key, options, fetcher);
```

**`makeServerFetchye` Arguments**
**`makeOneServerFetchye` Arguments**

| name | type | required | description |
|---|---|---|---|
| `cache` | `Cache` | `false` | *Defaults to OneCache* Fetchye `Cache` object. |
| `fetchClient` | `ES6Fetch` | `true` | A [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) compatible function. |
| `store` | `Store` | `true` | A [Redux Store](https://redux.js.org/api/store)
| `store` | `Store` | `true` | A [Redux Store](https://redux.js.org/api/store) |

**`fetchye` Arguments**

Expand All @@ -919,6 +920,34 @@
| `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* |


### oneFetchye

Call fetchye in an imperative context, such as in One App's loadModuleData, in a Redux Thunk, or in an useEffect.

**Shape**

```
const { data, error } = await dispatch(onefetchye(key, options, fetcher));
```

**`onefetchye` Arguments**

| name | type | required | description |
|-----------|------------------------------------------------------------------------------------------------------|------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
| `key` | `String` or `() => String` | `true` | A string or function returning a string that factors into cache key creation. *Defaults to URL compatible string*. |
| `options` | `ES6FetchOptions` | `false` | Options to pass through to [ES6 Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). |
| `fetcher` | `async (fetchClient: Fetch, key: String, options: Options) => ({ 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. |

**`onefetchye` Returns**

A promise resolving to an object with the below keys:

| name | type | description |
|----------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `data` | `Object` | A result of a `fetchClient` query. *Defaults to returning `{ status, body, ok, headers }` from `fetchClient` response* |
| `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* |


### Providers

A Provider creates a React Context to connect all the `useFetchye` Hooks into a centrally stored cache.
Expand Down
33 changes: 33 additions & 0 deletions packages/fetchye-one-app/__tests__/oneFetchye.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import oneFetchye from '../src/oneFetchye';

const mockOneCacheSymbol = Symbol('oneCache');
jest.mock('../src/OneCache', () => jest.fn(() => mockOneCacheSymbol));
jest.mock('fetchye', () => ({
makeServerFetchye: jest.fn((...makeFetchyeArgs) => jest.fn((...fetcheArgs) => Promise.resolve(
{ makeFetchyeArgs, fetcheArgs }
))),
}));
describe('oneFetchye', () => {
it('should return a one-app-thunk that calls fetchye', async () => {
expect.assertions(1);
const fetchyeParams = [Symbol('fetchyeArgs 1'), Symbol('fetchyeArgs 2')];
const fetchyeThunk = oneFetchye(...fetchyeParams);
const thunkParams = [Symbol('dispatch'), Symbol('getState'), Symbol('fetchClient')];
const response = await fetchyeThunk(
thunkParams[0], thunkParams[1], { fetchClient: thunkParams[2] }
);
expect(response).toStrictEqual({
fetcheArgs: fetchyeParams,
makeFetchyeArgs: [
{
cache: mockOneCacheSymbol,
fetchClient: thunkParams[2],
store: {
dispatch: thunkParams[0],
getState: thunkParams[1],
},
},
],
});
});
});
1 change: 1 addition & 0 deletions packages/fetchye-one-app/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
export { makeOneServerFetchye } from './makeOneServerFetchye';
export OneCache, { oneCacheSelector } from './OneCache';
export OneFetchyeProvider from './OneFetchyeProvider';
export oneFetchye from './oneFetchye';
13 changes: 13 additions & 0 deletions packages/fetchye-one-app/src/oneFetchye.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { makeServerFetchye } from 'fetchye';
import OneCache from './OneCache';

const oneFetchye = (...fetchyeArgs) => async (dispatch, getState, { fetchClient }) => {
const fetchye = makeServerFetchye({
store: { getState, dispatch },
fetchClient,
cache: OneCache(),
});
return fetchye(...fetchyeArgs);
};

export default oneFetchye;
Loading