Socket
Socket
Sign inDemoInstall

@shopify/react-effect

Package Overview
Dependencies
Maintainers
13
Versions
75
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@shopify/react-effect - npm Package Compare versions

Comparing version 3.0.0-beta.1 to 3.0.0

dist/manager.d.ts

15

CHANGELOG.md

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

## [3.0.0] - 2019-04-08
This library now requires React 16.8.
### Added
- Added a `useServerEffect` hook as an alternative to the `<Effect />` component ([#547](https://github.com/Shopify/quilt/pull/547))
## [2.1.0]
### Added
- Added a `maxPasses` option to `extract()` in order to limit the potential for infinite loops. This option defaults to 5 max render/ resolve cycles [#574](https://github.com/Shopify/quilt/pull/574)
- All `afterEachPass`/ `betweenEachPass` callbacks now receive an argument detailing the current pass index, whether the extraction process is complete, and the duration of the render/ resolve phases [#574](https://github.com/Shopify/quilt/pull/574)
## [2.0.0]

@@ -12,0 +27,0 @@

20

dist/context.d.ts
import * as React from 'react';
import { EffectKind } from './types';
interface Options {
include?: symbol[] | boolean;
}
export declare class EffectManager {
private include;
private effects;
private kinds;
readonly finished: boolean;
constructor({ include }?: Options);
add(effect: any, kind?: EffectKind): void;
resolve(): Promise<void>;
betweenEachPass(): void;
afterEachPass(): void;
shouldPerform(kind: EffectKind): boolean;
}
export declare const EffectContext: React.Context<EffectManager | undefined>;
export {};
import { EffectManager } from './manager';
export declare const EffectContext: React.Context<EffectManager | null>;

@@ -5,85 +5,2 @@ "use strict";

var React = tslib_1.__importStar(require("react"));
var EffectManager = /** @class */ (function () {
function EffectManager(_a) {
var _b = (_a === void 0 ? {} : _a).include, include = _b === void 0 ? true : _b;
this.effects = [];
this.kinds = new Set();
this.include = include;
}
Object.defineProperty(EffectManager.prototype, "finished", {
get: function () {
return this.effects.length === 0;
},
enumerable: true,
configurable: true
});
EffectManager.prototype.add = function (effect, kind) {
if (kind != null) {
this.kinds.add(kind);
}
if (effect == null || !('then' in effect)) {
return;
}
this.effects.push(effect);
};
EffectManager.prototype.resolve = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Promise.all(this.effects)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
EffectManager.prototype.betweenEachPass = function () {
var e_1, _a;
try {
for (var _b = tslib_1.__values(this.kinds), _c = _b.next(); !_c.done; _c = _b.next()) {
var kind = _c.value;
if (typeof kind.betweenEachPass === 'function') {
kind.betweenEachPass();
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
};
EffectManager.prototype.afterEachPass = function () {
var e_2, _a;
try {
for (var _b = tslib_1.__values(this.kinds), _c = _b.next(); !_c.done; _c = _b.next()) {
var kind = _c.value;
if (typeof kind.afterEachPass === 'function') {
kind.afterEachPass();
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_2) throw e_2.error; }
}
this.effects = [];
this.kinds = new Set();
};
EffectManager.prototype.shouldPerform = function (kind) {
var include = this.include;
if (!include) {
return false;
}
return include === true || (kind != null && include.includes(kind.id));
};
return EffectManager;
}());
exports.EffectManager = EffectManager;
exports.EffectContext = React.createContext(undefined);
exports.EffectContext = React.createContext(null);

@@ -6,3 +6,3 @@ import { EffectKind } from './types';

}
export default function Effect({ kind, perform }: Props): null;
export declare function Effect({ kind, perform }: Props): null;
export {};

@@ -9,2 +9,2 @@ "use strict";

}
exports.default = Effect;
exports.Effect = Effect;

@@ -1,5 +0,5 @@

export { default as Effect } from './Effect';
export { EffectManager } from './context';
export { Effect } from './Effect';
export { EffectManager } from './manager';
export { EffectKind } from './types';
export { useServerEffect } from './hook';
export { restrictToServer } from './utilities';
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Effect_1 = require("./Effect");
exports.Effect = Effect_1.default;
var context_1 = require("./context");
exports.EffectManager = context_1.EffectManager;
exports.Effect = Effect_1.Effect;
var manager_1 = require("./manager");
exports.EffectManager = manager_1.EffectManager;
var hook_1 = require("./hook");

@@ -8,0 +8,0 @@ exports.useServerEffect = hook_1.useServerEffect;

import * as React from 'react';
import { Pass } from './types';
export { Effect } from './Effect';
interface Options {
include?: symbol[] | boolean;
maxPasses?: number;
decorate?(element: React.ReactElement<any>): React.ReactElement<any>;
renderFunction?(element: React.ReactElement<{}>): string;
betweenEachPass?(): any;
afterEachPass?(): any;
betweenEachPass?(pass: Pass): any;
afterEachPass?(pass: Pass): any;
}
export declare function extract(app: React.ReactElement<any>, { include, decorate, renderFunction, betweenEachPass, afterEachPass, }?: Options): Promise<string>;
export {};
export declare function extract(app: React.ReactElement<any>, { include, maxPasses, decorate, renderFunction, betweenEachPass, afterEachPass, }?: Options): Promise<string>;

@@ -7,19 +7,36 @@ "use strict";

var context_1 = require("./context");
var manager_1 = require("./manager");
var Effect_1 = require("./Effect");
exports.Effect = Effect_1.Effect;
var DEFAULT_MAX_PASSES = 5;
function extract(app, _a) {
var _b = _a === void 0 ? {} : _a, include = _b.include, _c = _b.decorate, decorate = _c === void 0 ? identity : _c, _d = _b.renderFunction, renderFunction = _d === void 0 ? server_1.renderToStaticMarkup : _d, betweenEachPass = _b.betweenEachPass, afterEachPass = _b.afterEachPass;
var manager = new context_1.EffectManager({ include: include });
var _b = _a === void 0 ? {} : _a, include = _b.include, _c = _b.maxPasses, maxPasses = _c === void 0 ? DEFAULT_MAX_PASSES : _c, _d = _b.decorate, decorate = _d === void 0 ? identity : _d, _e = _b.renderFunction, renderFunction = _e === void 0 ? server_1.renderToStaticMarkup : _e, betweenEachPass = _b.betweenEachPass, afterEachPass = _b.afterEachPass;
var manager = new manager_1.EffectManager({ include: include });
var element = (React.createElement(context_1.EffectContext.Provider, { value: manager }, decorate(app)));
return (function perform() {
return (function perform(index) {
if (index === void 0) { index = 0; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var result;
var start, result, duration, resolveStart, renderDuration, resolveDuration;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
start = Date.now();
result = renderFunction(element);
if (!manager.finished) return [3 /*break*/, 4];
return [4 /*yield*/, manager.afterEachPass()];
duration = Date.now() - start;
return [4 /*yield*/, manager.afterEachPass({
index: index,
finished: manager.finished,
renderDuration: duration,
resolveDuration: 0,
})];
case 1:
_a.sent();
if (!afterEachPass) return [3 /*break*/, 3];
return [4 /*yield*/, afterEachPass()];
return [4 /*yield*/, afterEachPass({
index: index,
finished: manager.finished,
renderDuration: duration,
resolveDuration: 0,
})];
case 2:

@@ -29,22 +46,50 @@ _a.sent();

case 3: return [2 /*return*/, result];
case 4: return [4 /*yield*/, manager.resolve()];
case 4:
resolveStart = Date.now();
renderDuration = resolveStart - start;
return [4 /*yield*/, manager.resolve()];
case 5:
_a.sent();
return [4 /*yield*/, manager.betweenEachPass()];
resolveDuration = Date.now() - resolveStart;
return [4 /*yield*/, manager.betweenEachPass({
index: index,
finished: false,
renderDuration: renderDuration,
resolveDuration: resolveDuration,
})];
case 6:
_a.sent();
if (!betweenEachPass) return [3 /*break*/, 8];
return [4 /*yield*/, betweenEachPass()];
return [4 /*yield*/, betweenEachPass({
index: index,
finished: false,
renderDuration: renderDuration,
resolveDuration: resolveDuration,
})];
case 7:
_a.sent();
_a.label = 8;
case 8: return [4 /*yield*/, manager.afterEachPass()];
case 8: return [4 /*yield*/, manager.afterEachPass({
index: index,
finished: false,
renderDuration: renderDuration,
resolveDuration: resolveDuration,
})];
case 9:
_a.sent();
if (!afterEachPass) return [3 /*break*/, 11];
return [4 /*yield*/, afterEachPass()];
return [4 /*yield*/, afterEachPass({
index: index,
finished: false,
renderDuration: renderDuration,
resolveDuration: resolveDuration,
})];
case 10:
_a.sent();
_a.label = 11;
case 11: return [2 /*return*/, perform()];
case 11:
if (index + 1 >= maxPasses) {
return [2 /*return*/, result];
}
return [2 /*return*/, perform(index + 1)];
}

@@ -51,0 +96,0 @@ });

@@ -0,5 +1,11 @@

export interface Pass {
index: number;
finished: boolean;
renderDuration: number;
resolveDuration: number;
}
export interface EffectKind {
readonly id: symbol;
betweenEachPass?(): any;
afterEachPass?(): any;
betweenEachPass?(pass: Pass): any;
afterEachPass?(pass: Pass): any;
}
{
"name": "@shopify/react-effect",
"version": "3.0.0-beta.1",
"version": "3.0.0",
"license": "MIT",

@@ -26,3 +26,3 @@ "description": "A component and set of utilities for performing effects within a universal React app",

"dependencies": {
"@shopify/useful-types": "^1.1.2",
"@shopify/useful-types": "^1.2.1",
"tslib": "^1.9.3"

@@ -29,0 +29,0 @@ },

@@ -38,3 +38,3 @@ # `@shopify/react-effect`

This component is now deprecated in favour of `useServerEffect`. It will removed in the next major version of `@shopify/react-effect`.
This is a component version of `useServerEffect`. Its `perform` prop will be run as a server effect, and its `kind` prop is used as the second argument to `useServerEffect`. Where possible, prefer the `useServerEffect` hook.

@@ -72,3 +72,3 @@ ### `extract()`

// will only perform @shopify/react-i18n extraction
await extract(app, [I18N_EFFECT_ID]);
await extract(app, {include: [I18N_EFFECT_ID]});
ctx.body = renderToString(app);

@@ -78,6 +78,8 @@ }

- `betweenEachPass`: a function that is called after a pass of your tree that did not "finish" (that is, there were still promises that got collected). This function can return a promise, and it will be waited on before continuing.
- `maxPasses`: a number that limits the number of render/ resolve cycles `extract` is allowed to perform. This option defaults to `5`.
- `afterEachPass`: a function that is called after each pass of your tree, regardless of whether traversal is "finished". This function can return a promise, and it will be waited on before continuing.
- `betweenEachPass`: a function that is called after a pass of your tree that did not "finish" (that is, there were still promises that got collected). This function can return a promise, and it will be waited on before continuing. It is called with a single argument: a `Pass` object, which contains the `index`, `finished`, `renderDuration` and `resolveDuration` of the just-completed pass.
- `afterEachPass`: a function that is called after each pass of your tree, regardless of whether traversal is "finished". This function can return a promise, and it will be waited on before continuing. This function is called with the same argument as the `betweenEachPass` option.
- `decorate`: a function that takes the root React element in your tree and returns a new tree to use. You can use this to wrap your application in context providers that only your server render requires.

@@ -84,0 +86,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