undux
Version:
Dead simple state management for React
63 lines • 2.85 kB
JavaScript
import * as React from 'react';
import { createStore, } from '..';
import { getDisplayName, mapValues } from '../utils';
export function createConnectedStoreAs(initialStates, effects) {
let Context = React.createContext({ __MISSING_PROVIDER__: true });
class Container extends React.Component {
constructor(props) {
super(props);
// Create store definition from initial state
let states = props.initialStates || initialStates;
let stores = mapValues(states, (_) => createStore(_));
// Apply effects?
let fx = props.effects || effects;
if (fx) {
fx(stores); // TODO
}
this.state = {
storeDefinitions: stores,
// TODO
storeSnapshots: mapValues(stores, (_) => _.getCurrentSnapshot()),
subscriptions: mapValues(stores, (_, k) => _.onAll().subscribe(() => this.setState((state) => ({
storeSnapshots: Object.assign({}, state.storeSnapshots, {
[k]: _.getCurrentSnapshot(),
}),
})))),
};
}
componentWillUnmount() {
mapValues(this.state.subscriptions, (_) => _.unsubscribe());
// Let the state get GC'd.
// TODO: Find a more elegant way to do this.
mapValues(this.state.storeSnapshots, (_) => (_.state = null));
mapValues(this.state.storeSnapshots, (_) => (_.storeDefinition = null));
mapValues(this.state.storeDefinitions, (_) => (_.storeSnapshot = null));
}
render() {
return (React.createElement(Context.Provider, { value: this.state.storeSnapshots }, this.props.children));
}
}
let Consumer = (props) => (React.createElement(Context.Consumer, null, (stores) => {
if (!isInitialized(stores)) {
throw Error(`[Undux] Component "${props.displayName}" does not seem to be nested in an Undux <Container>. To fix this error, be sure to render the component in the <Container>...</Container> component that you got back from calling createConnectedStoreAs().`);
}
return props.children(stores);
}));
function withStores(Component) {
let displayName = getDisplayName(Component);
let f = (props) => (React.createElement(Consumer, { displayName: displayName }, (stores) => React.createElement(Component, { ...stores, ...props })));
f.displayName = `withStores(${displayName})`;
return f;
}
return {
Container,
useStores() {
return React.useContext(Context);
},
withStores,
};
}
function isInitialized(store) {
return !('__MISSING_PROVIDER__' in store);
}
//# sourceMappingURL=createConnectedStoreAs.js.map