Skip to content

Instantly share code, notes, and snippets.

@vcardins
Last active May 5, 2017 16:50
Show Gist options
  • Save vcardins/f7ddfc91039b40c18eff447441a5be46 to your computer and use it in GitHub Desktop.
Save vcardins/f7ddfc91039b40c18eff447441a5be46 to your computer and use it in GitHub Desktop.
Baobab branch decorator issue
import * as React from 'react';
import { root, branch } from 'baobab-react/higher-order';
// Here is the problem. It does not return the data stored in the cursor ['user', 'model'] but undefined instead
// if I have only user: ['user'], it returns the user branch { user: { model: { ... }}, but then I have to deconstruct
// const { model: user = {} ) = this.props.user to get the actual data
@branch({
user: ['user', 'model'],
})
class App extends BaseComponent<Props, State> {
constructor(props: Props) {
super();
}
componentDidMount() {
const { dispatch, router } = this.props;
if (!UserAuth.isAuthenticated()) {
browserHistory.replace(appSettings.loginRoute);
} else {
UserAction.loadProfile();
}
}
render(): JSX.Element {
const { user } = this.props;
}
}
import { Api } from 'core/helpers';
import State from 'state';
class DataStore<T> {
private endpoint: string = null;
private rootCursor: any;
private ajaxCursor: any;
private modelsCursor: any;
private modelCursor: any;
// Initialize default values.
model: T;
models: Array<T>;
// Cache parameters
cache: any = {
count: {},
fetch: {},
load: {},
};
// Is scope used with data model or not, if yes this is actual scope
scope: boolean = false;
// Scope item names for single, collection and count
itemNames: any = {
model: false,
models: false,
count: false,
};
// destinationPath.concat(['models'])
/**
* Constructor for actual data model.
*
* @param {string} [endpoint] Name of the API endpoint
* @constructor
*/
constructor(endpoint: string, branch: string, key: string = 'id') {
// Subscribe to specified endpoint
if (!endpoint) {
throw Error('Data Store domain needs to be set');
}
this.endpoint = endpoint;
this._subscribe();
this.modelsCursor = State.select([branch].concat(['models']));
this.modelCursor = State.select([branch].concat(['model']));
this.rootCursor = State.select();
this.ajaxCursor = this.rootCursor.select(['ajax']);
}
private setProgress (inProgress: boolean) {
this.ajaxCursor.set('loading', inProgress);
}
private setError (error: Error) {
this.ajaxCursor.set('error', error);
}
private loadModels(params: any = {}, endpoint: string = null, cursor: any): Promise<T | Array<T>> {
this.setProgress(true);
return Api
.get(endpoint || this.endpoint, params)
.then((response) => {
cursor.set(response);
this.setProgress(false);
State.commit();
return response;
})
.catch(this.setError);
}
getSingle(params: any = {}, endpoint: string = null, isSingleModel: boolean = false): Promise<T> {
return this.loadModels(params, endpoint, this.modelCursor);
}
get(params: any = {}, endpoint: string = null, isSingleModel: boolean = false): Promise<Array<T>> {
return this.loadModels(params, endpoint, this.modelsCursor);
}
}
export default DataStore;
import { monkey } from 'baobab';
const defaultFilters = {
pageSize: 100,
pageNumber: 0,
};
function defaultDataset (extras = {}) {
return Object.assign({
models: [],
modelsMap: {},
localFilters: Object.assign({}, defaultFilters),
filters: monkey({
cursors: {
globalFilters: ['globalFilters'],
localFilters: ['.', 'localFilters'],
},
get ({ globalFilters, localFilters }) {
return Object.assign({}, globalFilters, localFilters);
},
}),
checked: [],
highlighted: [],
selection: {},
}, extras);
}
// Default state values
const coreState = {
// General App State
appVersion: null,
isAppVersionUpdated: false,
loading: false,
preload: true,
debugModeOn: process.env.NODE_ENV !== 'production',
user: {},
lookup: {},
pendingUpdates: {},
};
const StateDefaults = Object.assign({}, coreState);
export default StateDefaults;
import * as Baobab from 'baobab';
import StateDefaults from './defaults';
const State = new Baobab(StateDefaults, {
// autoCommit boolean [true]: should the tree auto commit updates or should it let the user do so through the commit method?
autoCommit: false,
// asynchronous boolean [true]: should the tree delay the update to the next frame or fire them synchronously?
// asynchronous: false,
// immutable boolean [true]: should the tree's data be immutable? Note that immutability is performed through Object.freeze and should be disabled in production for performance reasons.
immutable: true,
// lazyMonkeys boolean [true]: should the monkeys be lazy? Disable this option for easier debugging in your console (getter functions are sometimes hard to read in the console).
// lazyMonkeys: true,
// persistent boolean [true]: should the tree be persistent. Know that disabling this option, while bringing a significant performance boost on heavy data, will make you lose the benefits of your tree's history and O(1) comparisons of objects.
// persistent: false,
// pure boolean [true]: by default, on set and apply operations, the tree will check if the given value and the target node are stricly equal. If they indeed are, the tree won't update.
// pure: false,
// validate function: a function in charge of validating the tree whenever it updates. See below for an example of such function.
// validate: () => {},
// validationBehavior string [rollback]: validation behavior of the tree. If rollback, the tree won't apply the current update and fire an invalid event while notify will only emit the event and let the tree enter the invalid state anyway.
// validationBehavior: 'rollback',
});
export default State;
import UserProfile from './UserProfile';
import IUserAction from './IUserAction';
import State from 'state';
import DataStore from 'core/data/DataStore';
const userDataStore = new DataStore<UserProfile>('profile', 'user', 'userId');
const UserAction: IUserAction = {
loadProfile(): void {
userDataStore.getSingle().then((profile: any) => profile);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment