Skip to content

Instantly share code, notes, and snippets.

@developit
Created January 7, 2017 22:44
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save developit/d1d9d4c224ec76d55d0503c295030f92 to your computer and use it in GitHub Desktop.
Save developit/d1d9d4c224ec76d55d0503c295030f92 to your computer and use it in GitHub Desktop.
Demonstrates compositional components in Preact (or React). Live demo: https://jsfiddle.net/developit/umnb4y87/
import { h, cloneElement, Component } from 'preact';
/** Example <Fetch url="/foo.json" /> compositional component.
* Just to demonstrate a compositional component that requires input massaging.
*/
class Fetch extends Component {
state = { loading: true };
componentDidMount() {
this.update();
}
componentDidUpdate(prevProps) {
if (this.props.url!==prevProps.url) {
this.update();
}
}
update() {
let { url, as='json' } = this.props;
this.setState({ loading:true, error:null });
fetch(url)
.then( r => r[as]() )
.then( data => this.setState({ loading:false, data }) )
.catch( error => this.setState({ loading:false, error }) );
}
render(props, state) {
// just pass all state to the child as props
return cloneElement(props.children[0], state);
}
}
/** "Smart" component, akin to a Controller.
* Typically arguments/props to this come from the URL.
*/
const ProfilePage = ({ id }) => (
<Fetch url={'/user/'+encodeURIComponent(id)} as="json">
<ProfileView full={true} />
</Fetch>
);
/** "Dumb" view component, analagous to a template */
const ProfileView = ({ loading, data, error }) => (
<div class="some-view" data-loading={loading}>
{ error && <ErrorBox error={error} /> }
{ data && (
<div class="profile">
<h1>{data.name}</h1>
<p>{data.bio}</p>
<a href={data.url} target="_blank">{data.urlName}</a>
</div>
) }
</div>
);
/** A "template partial" */
const ErrorBox = ({ error }) => (
<div class="error">
<h1>We have a problem!</h1>
<pre>{error.message}</pre>
</div>
);
// magic:
render(<ProfilePage id="5" />, document.body);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment