Skip to content

Instantly share code, notes, and snippets.

@hhff
Created July 31, 2018 15:29
Show Gist options
  • Save hhff/d124dd77038356e16a98f465adf59866 to your computer and use it in GitHub Desktop.
Save hhff/d124dd77038356e16a98f465adf59866 to your computer and use it in GitHub Desktop.
React on Ember
import React, { Component } from "react";
import get from "utils/get";
// Use extend ContainerBase in your Route Containers and use
// the provided lifecycle hooks to load data. This way you'll
// have a predictable edge to know when data is loaded for your
// Route - super useful for serverside rendering your app!
class ContainerBase extends Component {
state = {
view: null,
model: null,
error: null
};
view = "Undefined";
redirect = f => f;
beforeModel = f => f;
model = f => f;
afterModel = f => f;
activate = f => f;
runHooks = () => {
return new Promise(async resolve => {
let model;
try {
await this.beforeModel();
model = await this.model();
await this.afterModel(model);
if (model) model.isError = false;
else model = { isError: false };
} catch (error) {
model = { isError: true, error };
}
resolve(model);
});
};
async componentDidMount() {
this.redirect();
const [{ default: View }, model] = await Promise.all([
this.view,
this.runHooks()
]);
this.activate(model);
this.setState({ view: View, model });
}
async componentWillReceiveProps(nextProps) {
if (
get(this, "props.location.pathname") !==
get(nextProps, "location.pathname")
) {
this.redirect();
const [{ default: View }, model] = await Promise.all([
this.view,
this.runHooks()
]);
this.activate(model);
this.setState({ view: View, model });
}
}
render() {
const { view: View, model } = this.state;
return View ? <View model={model} {...this.props} /> : null;
}
}
export default ContainerBase;
import ContainerBase from "lib/ContainerBase";
import ContentfulData from 'lib/ContentfulData';
import { consideredLoading } from 'state/actions';
class StudiesContainer extends ContainerBase {
view = import("views/StudiesView");
model = () => {
consideredLoading(true);
return ContentfulData.getEntries({
content_type: 'study',
include: 2
}).then(res => {
consideredLoading(false);
return res.items;
}).catch(() => {
consideredLoading(false);
});
};
}
export default StudiesContainer;
import hashify from "object-hash";
// Call ContentfulData.setRef(contentful); early on, then use
// ContentfulData in place of the regular contentful ref to
// vastly lower requests made to Contentful during a session.
const ContentfulData = {
cache: {
getEntries: {}
},
setRef(contentful) {
this.contentful = contentful;
},
getEntries(query) {
const hashified = hashify(query);
if (!!this.cache.getEntries[hashified])
return new Promise(resolve => resolve(this.cache.getEntries[hashified]));
return this.contentful.getEntries(query).then(val => {
this.cache.getEntries[hashified] = val;
return val;
});
}
};
export default ContentfulData;
import get from 'lodash.get';
// Whenever digging into an Object, use get(obj, 'some.deep.property', []); to
// avoid TypeErrors, and always return the type you're looking for in the case
// the dig failed to yield a value
export default (obj, path='', fallback) => get(obj, path, fallback) || fallback;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment