Skip to content
This repository has been archived by the owner on May 27, 2022. It is now read-only.

Commit

Permalink
Merge pull request #106 from data-provider/release
Browse files Browse the repository at this point in the history
Release v1.5.0
  • Loading branch information
javierbrea authored Nov 16, 2020
2 parents 2695426 + 9cf212f commit 92cd4d0
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 22 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
### Removed

## [1.5.0] - 2020-11-16
### Added
- feat: Supports passing options to cleanCache methods in usePolling and withPolling

## [1.4.0] - 2020-11-09
### Added
- feat(hocs): Add withDataLoadedError, withDataLoadingError, withDataLoadingErrorComponents, withDataLoadedErrorComponents
Expand Down
26 changes: 21 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ const BooksList = () => {
};
```

### `usePolling(provider, [interval])`
### `usePolling(provider, [interval/options], [options])`

Triggers `cleanDependenciesCache` method of the provider each `interval` miliseconds while the component is "alive". It can be used in multiple components at the same time for the same provider. In that case, the used interval will be the lower one, and it will be recalculated each time a component is added or removed.

Expand All @@ -199,9 +199,10 @@ This hook can also be used with [Data Provider selectors][data-provider-selector
#### Arguments

* `provider` _(Object)_: [Data Provider][data-provider] provider or selector instance.
* `interval` _(Object)_: Interval in miliseconds to clean the provider dependencies cache. Default is 5000.
* `interval` _(Number)_: Interval in miliseconds to clean the provider dependencies cache. Default is 5000.
* `options` _(Object)_: Options object that will be passed as is to the `cleanCache` method of providers or `cleanDependenciesCache` method of selectors. Check the [data-provider API documentation](https://www.data-provider.org/docs/api-providers-and-selectors-methods) for further info. Options can be defined as second argument if interval is omitted.

#### Example
#### Examples

```jsx
import { useData, usePolling } from "@data-provider/react";
Expand All @@ -215,6 +216,20 @@ const BooksList = () => {
};
```

```jsx
import { useData, usePolling } from "@data-provider/react";

import { booksAndAuthors, books } from "../data/books";

const BooksList = () => {
const data = useData(books);
usePolling(booksAndAuthors, {
except: [books]
});
// Do your stuff here. booksAndAuthors selector dependencies will fetched again from server every 3 seconds, except the "books" provider.
};
```

## HOCs

### `withDataLoadingError(provider, [customPropertiesNames])(Component)`
Expand Down Expand Up @@ -430,14 +445,15 @@ const BooksList = ({ booksError }) => {
export default withError(books, "booksError")(BooksList);
```

### `withPolling(provider, [interval])(Component)`
### `withPolling(provider, [interval/options], [options])(Component)`

This High Order Component works as the hook `usePolling` described above.

#### Arguments

* `provider` _(Object)_: [Data Provider][data-provider] provider or selector instance, or a function as described in the [withDataLoadingError HOC docs](#withdataloadingerrorprovider-custompropertiesnamescomponent)
* `interval` _(Object)_: Interval in miliseconds to clean the provider dependencies cache. Default is 5000.
* `interval` _(Number)_: Interval in miliseconds to clean the provider dependencies cache. Default is 5000.
* `options` _(Object)_: Options object that will be passed as is to the `cleanCache` method of providers or `cleanDependenciesCache` method of selectors. Check the [data-provider API documentation](https://www.data-provider.org/docs/api-providers-and-selectors-methods) for further info. Options can be defined as second argument if interval is omitted.

#### Example

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@data-provider/react",
"version": "1.4.0",
"version": "1.5.0",
"description": "React bindings for @data-provider",
"keywords": [
"data-provider",
Expand Down
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
sonar.organization=data-provider
sonar.projectKey=data-provider-react
sonar.projectVersion=1.4.0
sonar.projectVersion=1.5.0

sonar.sources=src,test
sonar.exclusions=node_modules/**
Expand Down
31 changes: 23 additions & 8 deletions src/usePolling.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { useEffect } from "react";
import { useEffect, useMemo } from "react";

const DEFAULT_INTERVAL_TIME = 5000;
const pollingProviders = {};

class PollingHandler {
constructor(provider, intervalTime) {
constructor(provider, intervalTime, options) {
provider.cleanCache();
this._options = options;
this._provider = provider;
this._id = provider.id;
this._clients = 1;
Expand All @@ -16,7 +18,7 @@ class PollingHandler {

_setInterval() {
this._interval = setInterval(() => {
this._provider.cleanDependenciesCache();
this._provider.cleanDependenciesCache(this._options);
}, this._currentIntervalTime);
}

Expand Down Expand Up @@ -55,19 +57,32 @@ class PollingHandler {
}
}

export const usePolling = (provider, intervalTime = 5000) => {
export const usePolling = (provider, intervalTimeOrOptions, options = {}) => {
const [intervalTimeToUse, optionsToUse] = useMemo(() => {
if (typeof intervalTimeOrOptions === "undefined") {
return [DEFAULT_INTERVAL_TIME, options];
} else if (typeof intervalTimeOrOptions === "object") {
return [DEFAULT_INTERVAL_TIME, intervalTimeOrOptions];
}
return [intervalTimeOrOptions, options];
}, [intervalTimeOrOptions, options]);

useEffect(() => {
let clearProviderInterval;
if (provider) {
if (pollingProviders[provider.id]) {
pollingProviders[provider.id].addClient(intervalTime);
pollingProviders[provider.id].addClient(intervalTimeToUse);
} else {
pollingProviders[provider.id] = new PollingHandler(provider, intervalTime);
pollingProviders[provider.id] = new PollingHandler(
provider,
intervalTimeToUse,
optionsToUse
);
}
clearProviderInterval = () => {
pollingProviders[provider.id].removeClient(intervalTime);
pollingProviders[provider.id].removeClient(intervalTimeToUse);
};
}
return clearProviderInterval;
}, [provider, intervalTime]);
}, [provider, intervalTimeToUse]);
};
4 changes: 2 additions & 2 deletions src/withDataProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,10 @@ export const withError = (provider, key) => (Component) => {
return WithError;
};

export const withPolling = (provider, interval) => (Component) => {
export const withPolling = (provider, interval, options) => (Component) => {
const WithPolling = (props) => {
const providerToRead = useProvider(provider, props);
usePolling(providerToRead, interval);
usePolling(providerToRead, interval, options);
return <Component {...props} />;
};
hoistNonReactStatics(WithPolling, Component);
Expand Down
55 changes: 53 additions & 2 deletions test/usePolling.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import React, { useState, useEffect } from "react";
import "@testing-library/jest-dom";
import { render, act } from "@testing-library/react";
import { providers } from "@data-provider/core";
import { providers, Selector } from "@data-provider/core";
import sinon from "sinon";

import { usePolling, useData } from "../src";
Expand All @@ -20,13 +20,14 @@ const wait = (time = 600) => {
};

describe("usePolling", () => {
let sandbox, provider, BooksComponent, Component;
let sandbox, provider, BooksComponent, Component, selector;

beforeEach(() => {
sandbox = sinon.createSandbox();
provider = new MockProvider(BOOKS_ID, {
data: BOOKS,
});
selector = new Selector(provider, (result) => result);
sandbox.spy(provider, "cleanCache");
});

Expand Down Expand Up @@ -136,4 +137,54 @@ describe("usePolling", () => {
expect(provider.cleanCache.callCount).toEqual(4);
});
});

describe("when using except option", () => {
beforeEach(() => {
const OPTIONS = {
except: [provider],
};
BooksComponent = () => {
const books = useData(selector);
usePolling(selector, 500, OPTIONS);
return <Books books={books} />;
};

Component = () => (
<ReduxProvider>
<BooksComponent />
</ReduxProvider>
);
});

it("should not clean the provider cache as it is defined in except option", async () => {
render(<Component />);
await wait(3000);
expect(provider.cleanCache.callCount).toEqual(0);
});
});

describe("when using options as first argument", () => {
beforeEach(() => {
const OPTIONS = {
except: [provider],
};
BooksComponent = () => {
const books = useData(selector);
usePolling(selector, OPTIONS);
return <Books books={books} />;
};

Component = () => (
<ReduxProvider>
<BooksComponent />
</ReduxProvider>
);
});

it("should not clean the provider cache as it is defined in except option", async () => {
render(<Component />);
await wait(8000);
expect(provider.cleanCache.callCount).toEqual(0);
}, 10000);
});
});
57 changes: 55 additions & 2 deletions test/withPolling.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import React, { useState, useEffect } from "react";
import "@testing-library/jest-dom";
import { render, act } from "@testing-library/react";
import { providers } from "@data-provider/core";
import { providers, Selector } from "@data-provider/core";
import sinon from "sinon";

import { withPolling, useData } from "../src";
Expand All @@ -20,13 +20,14 @@ const wait = (time = 600) => {
};

describe("withPolling", () => {
let sandbox, provider, BooksComponent, BooksComponentToRender, Component;
let sandbox, provider, BooksComponent, BooksComponentToRender, Component, selector;

beforeEach(() => {
sandbox = sinon.createSandbox();
provider = new MockProvider(BOOKS_ID, {
data: BOOKS,
});
selector = new Selector(provider, (result) => result);
sandbox.spy(provider, "cleanCache");
});

Expand Down Expand Up @@ -151,4 +152,56 @@ describe("withPolling", () => {
expect(provider.cleanCache.callCount).toEqual(4);
});
});

describe("when using except option", () => {
beforeEach(() => {
const OPTIONS = {
except: [provider],
};
BooksComponent = () => {
const books = useData(selector);
return <Books books={books} />;
};

BooksComponentToRender = withPolling(selector, 500, OPTIONS)(BooksComponent);

Component = () => (
<ReduxProvider>
<BooksComponentToRender />
</ReduxProvider>
);
});

it("should not clean the provider cache as it is defined in except option", async () => {
render(<Component />);
await wait(3000);
expect(provider.cleanCache.callCount).toEqual(0);
});
});

describe("when using options as first argument", () => {
beforeEach(() => {
const OPTIONS = {
except: [provider],
};
BooksComponent = () => {
const books = useData(selector);
return <Books books={books} />;
};

BooksComponentToRender = withPolling(selector, OPTIONS)(BooksComponent);

Component = () => (
<ReduxProvider>
<BooksComponent />
</ReduxProvider>
);
});

it("should not clean the provider cache as it is defined in except option", async () => {
render(<Component />);
await wait(8000);
expect(provider.cleanCache.callCount).toEqual(0);
}, 10000);
});
});

0 comments on commit 92cd4d0

Please sign in to comment.