Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@shopify/react-async

Package Overview
Dependencies
Maintainers
12
Versions
170
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@shopify/react-async - npm Package Compare versions

Comparing version 1.0.2 to 1.1.0

7

CHANGELOG.md

@@ -10,2 +10,9 @@ # Changelog

## 1.1.0 - 2019-02-15
### Added
- `createAsyncComponent` now accepts a `defer` property that dictates whether that component should wait until mount or idle to start loading the component ([#517](https://github.com/Shopify/quilt/pull/517))
- The component returned from `createAsyncComponent` and its static `Preload`, `Prefetch`, and `KeepFresh` components all accept an `async` prop that is an object with an optional `defer` property, which controls the way loading is done for just that element ([#517](https://github.com/Shopify/quilt/pull/517))
## 1.0.2 - 2019-02-10

@@ -12,0 +19,0 @@

7

dist/Async.d.ts
import * as React from 'react';
import { LoadProps } from '@shopify/async';
import { Omit } from '@shopify/useful-types';
import { DeferTiming } from './shared';
import { AsyncAssetManager } from './context/assets';
interface Props<Value> extends LoadProps<Value> {
defer?: boolean;
export interface AsyncPropsRuntime {
defer?: DeferTiming;
}
interface Props<Value> extends LoadProps<Value>, AsyncPropsRuntime {
manager?: AsyncAssetManager;

@@ -8,0 +11,0 @@ render?(value: Value | null): React.ReactNode;

@@ -6,4 +6,4 @@ "use strict";

var react_effect_1 = require("@shopify/react-effect");
var shared_1 = require("./shared");
var assets_1 = require("./context/assets");
/* eslint-enable camelcase */
var ConnectedAsync = /** @class */ (function (_super) {

@@ -19,5 +19,12 @@ tslib_1.__extends(ConnectedAsync, _super);

this.mounted = false;
if (this.idleCallbackHandle != null && 'cancelIdleCallback' in window) {
window.cancelIdleCallback(this.idleCallbackHandle);
}
};
ConnectedAsync.prototype.componentDidMount = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _this = this;
if (this.state.resolved != null) {
return;
}
var load = function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var resolved, error_1;

@@ -27,10 +34,5 @@ return tslib_1.__generator(this, function (_a) {

case 0:
if (this.state.resolved != null) {
return [2 /*return*/];
}
_a.label = 1;
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, this.props.load()];
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.props.load()];
case 2:
resolved = _a.sent();

@@ -40,10 +42,17 @@ if (this.mounted) {

}
return [3 /*break*/, 4];
case 3:
return [3 /*break*/, 3];
case 2:
error_1 = _a.sent();
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
});
}); };
if (this.props.defer === shared_1.DeferTiming.Idle &&
'requestIdleCallback' in window) {
this.idleCallbackHandle = window.requestIdleCallback(load);
}
else {
load();
}
};

@@ -66,3 +75,3 @@ ConnectedAsync.prototype.render = function () {

function initialState(props) {
var canResolve = !props.defer && props.id;
var canResolve = props.defer == null && props.id;
var resolved = canResolve && props.id ? tryRequire(props.id()) : null;

@@ -69,0 +78,0 @@ return {

import * as React from 'react';
import { LoadProps } from '@shopify/async';
import { Props as ComponentProps } from '@shopify/useful-types';
import { Async } from './Async';
import { Async, AsyncPropsRuntime } from './Async';
import { DeferTiming } from './shared';
interface ConstantProps {
async?: AsyncPropsRuntime;
}
interface Options<Props, PreloadProps = {}, PrefetchProps = {}, KeepFreshProps = {}> extends LoadProps<React.ComponentType<Props>> {
defer?: DeferTiming;
renderLoading?(): React.ReactNode;

@@ -12,8 +17,8 @@ renderPreload?(props?: PreloadProps): React.ReactNode;

export interface AsyncComponentType<Props, PreloadProps, PrefetchProps, KeepFreshProps> {
(props: Props): React.ReactElement<ComponentProps<typeof Async>>;
Preload(props: PreloadProps): React.ReactElement<{}>;
Prefetch(props: PrefetchProps): React.ReactElement<{}>;
KeepFresh(props: KeepFreshProps): React.ReactElement<{}>;
(props: Props & ConstantProps): React.ReactElement<ComponentProps<typeof Async>>;
Preload(props: PreloadProps & ConstantProps): React.ReactElement<{}>;
Prefetch(props: PrefetchProps & ConstantProps): React.ReactElement<{}>;
KeepFresh(props: KeepFreshProps & ConstantProps): React.ReactElement<{}>;
}
export declare function createAsyncComponent<Props, PreloadProps = {}, PrefetchProps = {}, KeepFreshProps = {}>({ load, id, renderLoading, renderPreload, renderPrefetch, renderKeepFresh, }: Options<Props, PreloadProps, PrefetchProps, KeepFreshProps>): AsyncComponentType<Props, PreloadProps, PrefetchProps, KeepFreshProps>;
export declare function createAsyncComponent<Props, PreloadProps = {}, PrefetchProps = {}, KeepFreshProps = {}>({ id, load, defer, renderLoading, renderPreload, renderPrefetch, renderKeepFresh, }: Options<Props, PreloadProps, PrefetchProps, KeepFreshProps>): AsyncComponentType<Props, PreloadProps, PrefetchProps, KeepFreshProps>;
export {};

@@ -6,21 +6,30 @@ "use strict";

var Async_1 = require("./Async");
var shared_1 = require("./shared");
function createAsyncComponent(_a) {
var load = _a.load, id = _a.id, renderLoading = _a.renderLoading, _b = _a.renderPreload, renderPreload = _b === void 0 ? noopRender : _b, _c = _a.renderPrefetch, renderPrefetch = _c === void 0 ? noopRender : _c, _d = _a.renderKeepFresh, renderKeepFresh = _d === void 0 ? noopRender : _d;
var id = _a.id, load = _a.load, defer = _a.defer, renderLoading = _a.renderLoading, _b = _a.renderPreload, renderPreload = _b === void 0 ? noopRender : _b, _c = _a.renderPrefetch, renderPrefetch = _c === void 0 ? noopRender : _c, _d = _a.renderKeepFresh, renderKeepFresh = _d === void 0 ? noopRender : _d;
function AsyncComponent(props) {
return (React.createElement(Async_1.Async, { load: load, id: id, renderLoading: renderLoading, render: function (Component) { return (Component ? React.createElement(Component, tslib_1.__assign({}, props)) : null); } }));
// Can't create a spread from union type, so opt for a function that
// does the dirty casting for us.
var _a = tslib_1.__read(splitProps(props), 2), componentProps = _a[0], asyncProps = _a[1];
return (React.createElement(Async_1.Async, tslib_1.__assign({ load: load, id: id, defer: defer, renderLoading: renderLoading, render: function (Component) {
return Component ? React.createElement(Component, tslib_1.__assign({}, componentProps)) : null;
} }, asyncProps)));
}
function Preload(props) {
var _a = tslib_1.__read(splitProps(props), 2), componentProps = _a[0], asyncProps = _a[1];
return (React.createElement(React.Fragment, null,
renderPreload(props),
React.createElement(Async_1.Async, { defer: true, load: load })));
renderPreload(componentProps),
React.createElement(Async_1.Async, tslib_1.__assign({ defer: shared_1.DeferTiming.Idle, load: load }, asyncProps))));
}
function Prefetch(props) {
var _a = tslib_1.__read(splitProps(props), 2), componentProps = _a[0], asyncProps = _a[1];
return (React.createElement(React.Fragment, null,
renderPrefetch(props),
React.createElement(Async_1.Async, { defer: true, load: load })));
renderPrefetch(componentProps),
React.createElement(Async_1.Async, tslib_1.__assign({ defer: shared_1.DeferTiming.Mount, load: load }, asyncProps))));
}
function KeepFresh(props) {
var _a = tslib_1.__read(splitProps(props), 2), componentProps = _a[0], asyncProps = _a[1];
return (React.createElement(React.Fragment, null,
renderKeepFresh(props),
React.createElement(Async_1.Async, { defer: true, load: load })));
renderKeepFresh(componentProps),
React.createElement(Async_1.Async, tslib_1.__assign({ defer: shared_1.DeferTiming.Idle, load: load }, asyncProps))));
}

@@ -40,1 +49,5 @@ // Once we upgrade past TS 3.1, this will no longer be necessary,

}
function splitProps(props) {
var _a = props, async = _a.async, rest = tslib_1.__rest(_a, ["async"]);
return [rest, async];
}

@@ -1,2 +0,2 @@

export { Async } from './Async';
export { Async, AsyncPropsRuntime } from './Async';
export { Prefetcher } from './Prefetcher';

@@ -6,3 +6,4 @@ export { PrefetchRoute } from './PrefetchRoute';

export { createAsyncContext, AsyncContextType } from './provider';
export { DeferTiming } from './shared';
export { AsyncAssetContext, AsyncAssetManager } from './context/assets';
export { PrefetchContext, PrefetchManager } from './context/prefetch';

@@ -13,2 +13,4 @@ "use strict";

exports.createAsyncContext = provider_1.createAsyncContext;
var shared_1 = require("./shared");
exports.DeferTiming = shared_1.DeferTiming;
var assets_1 = require("./context/assets");

@@ -15,0 +17,0 @@ exports.AsyncAssetContext = assets_1.AsyncAssetContext;

@@ -6,2 +6,3 @@ "use strict";

var Async_1 = require("./Async");
var shared_1 = require("./shared");
function createAsyncContext(_a) {

@@ -17,3 +18,3 @@ var id = _a.id, load = _a.load;

function Preload() {
return React.createElement(Async_1.Async, { defer: true, load: load });
return React.createElement(Async_1.Async, { defer: shared_1.DeferTiming.Idle, load: load });
}

@@ -20,0 +21,0 @@ return { Context: Context, Provider: Provider, Consumer: Consumer, Preload: Preload };

@@ -5,1 +5,5 @@ /// <reference types="react" />

} | React.ComponentType<Props>;
export declare enum DeferTiming {
Mount = 0,
Idle = 1
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var DeferTiming;
(function (DeferTiming) {
DeferTiming[DeferTiming["Mount"] = 0] = "Mount";
DeferTiming[DeferTiming["Idle"] = 1] = "Idle";
})(DeferTiming = exports.DeferTiming || (exports.DeferTiming = {}));
{
"name": "@shopify/react-async",
"version": "1.0.2",
"version": "1.1.0",
"license": "MIT",

@@ -5,0 +5,0 @@ "description": "Tools for creating powerful, asynchronously-loaded React components.",

@@ -84,3 +84,3 @@ # `@shopify/react-async`

```tsx
const MyQuery = createAsyncComponent({
const MyQuery = createAsyncQueryComponent({
load: () => import('./graphql/MyQuery.graphql'),

@@ -101,2 +101,58 @@ });

#### Deferring components
By default, components are loaded as early as possible. This means that, if the library can load your component synchronously, it will try to do so. If that is not possible, it will instead load it in `componentDidMount`. In some cases, a component may not be important enough to warrant being loaded early. This library exposes a few ways of "deferring" the loading of the component to an appropriate time.
If a component should always be deferred in some way, you can pass a custom `defer` option to `createAsyncComponent`. This property should be a member of the `DeferTiming` enum, which currently allows you to force deferring the component to either mount (`DeferTiming.Mount`) or until the browser is idle (`DeferTiming.Idle`; requires a polyfill for `window.requestIdleCallback`).
```tsx
import {createAsyncComponent, DeferTiming} from '@shopify/react-async';
// No deferring
const MyComponent = createAsyncComponent({
load: () => import('./MyComponent'),
});
// Never load synchronously, always start load in mount
const MyComponentOnMount = createAsyncComponent({
load: () => import('./MyComponent'),
defer: DeferTiming.Mount,
});
// Never load synchronously, always start load in requestIdleCallback
const MyComponentOnIdle = createAsyncComponent({
load: () => import('./MyComponent'),
defer: DeferTiming.Idle,
});
```
If you need to customize the deferring behaviour at runtime, the library always allows you to pass an `async` prop with some custom options for the underlying `<Async />` loader component (**note**: this library reserves the `async` prop name, so you can’t use that name for any of your component’s own props, or for the props you specify in the `renderPreload`, `renderPrefetch`, or `renderKeepFresh` options).
```tsx
import {createAsyncComponent, DeferTiming} from '@shopify/react-async';
// No deferring
const MyComponent = createAsyncComponent({
load: () => import('./MyComponent'),
});
// But this instance will defer until idle anyways
<MyComponent async={{defer: DeferTiming.Idle}} />;
```
This prop also works for the `Preload`, `Prefetch`, and `KeepFresh` components. Note that these components have default deferring behaviour that should work well for their intended use cases: `Preload` and `KeepFresh` defer until idle, and `Prefetch` defers until mount.
```tsx
const MyComponent = createAsyncComponent({
load: () => import('./MyComponent'),
});
// Deferring until later than usual
<MyComponent.Prefetch async={{defer: DeferTiming.Idle}} />
// Don’t defer at all
<MyComponent.Preload async={{defer: undefined}} />
<MyComponent.KeepFresh async={{defer: undefined}} />
```
### `PrefetchRoute` and `Prefetcher`

@@ -103,0 +159,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc