UNPKG

@rxreact/context

Version:

Dependency-inject an RxJS signal graph into your React components

112 lines (102 loc) 5.05 kB
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