@rxreact/context
Version:
Dependency-inject an RxJS signal graph into your React components
112 lines (102 loc) • 5.05 kB
JavaScript
import { Subject, merge } from 'rxjs';
import { map, distinctUntilChanged, scan, shareReplay } from 'rxjs/operators';
import { createContext, useState, useContext, useEffect, createElement } from 'react';
import { withViewModel } from '@rxreact/core';
var getAccessor = function (externalValue$) {
var setValue$ = new Subject();
var value$ = merge(setValue$, externalValue$);
return [value$, setValue$];
};
/**
* An operator to extract a property from an observable of an object.
* Useful for pulling a specific prop from an observable of React props.
* @param prop - The name of the object property
* @returns - An observable of the object's property
*/
function getProp(prop) {
return function (props$, compare) {
return props$.pipe(map(function (props) { return props[prop]; }), distinctUntilChanged(compare));
};
}
function reducer(pairs, startWith) {
var xs = pairs.map(function (_a, index) {
var observable = _a[0], _mapper = _a[1];
return observable.pipe(map(function (value) { return ({ index: index, payload: value }); }));
});
return merge.apply(void 0, xs).pipe(scan(function (state, _a) {
var index = _a.index, payload = _a.payload;
var _b = pairs[index], f = _b[1];
return f(state, payload);
}, startWith), shareReplay(1));
}
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function connect(context, viewModelFactory) {
return function connectWithComponent(Component) {
// The final component takes all the props of `component`,
// _except_ the ones passed in from the Signal Graph.
var Connected = function (props) {
// The Child component to render
var _a = useState({ Child: null }), Child = _a[0].Child, setChild = _a[1];
var _b = useState(null), localSubscriptions = _b[0], setLocalSubscriptions = _b[1];
var signalGraph = useContext(context);
// Wrap the child with `withViewModel`, but only do this once.
useEffect(function () {
var child = withViewModel(function (ownProps) {
var _a = viewModelFactory(signalGraph, ownProps), inputs = _a.inputs, outputs = _a.outputs, unsubscribe = _a.unsubscribe;
// Store the unsubscribes for cleanup.
setLocalSubscriptions(unsubscribe || null);
return { inputs: inputs, outputs: outputs };
})(Component);
// Wrap the child in an object, because `setChild` when passed a
// function (like a component) will actually call the function.
setChild({ Child: child });
}, [signalGraph]);
// On destroy, perform cleanup
useEffect(function () {
return function () {
if (localSubscriptions) {
localSubscriptions.map(function (subscription) { return subscription.unsubscribe(); });
}
};
}, [localSubscriptions]);
return Child ? createElement(Child, __assign({}, props)) : null;
};
return Connected;
};
}
/**
* Generate a SignalGraph context and provider to serve connected components.
* @param createSignalGraph - A function to generate the signal graph
*/
function createSignalGraphContext(createSignalGraph) {
var signalGraph = createSignalGraph();
var SignalGraphContext = createContext(signalGraph);
var SignalGraphProvider = function (_a) {
var children = _a.children;
return (createElement(SignalGraphContext.Provider, { value: signalGraph }, children));
};
return [SignalGraphContext, SignalGraphProvider];
}
export { connect, createSignalGraphContext, getAccessor, getProp, reducer };
//# sourceMappingURL=context.es5.js.map