Skip to content

Instantly share code, notes, and snippets.

@epelz
Last active June 14, 2017 05:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save epelz/430d8ab4f1b07c65624cd442997d1ef0 to your computer and use it in GitHub Desktop.
Save epelz/430d8ab4f1b07c65624cd442997d1ef0 to your computer and use it in GitHub Desktop.
/**
* A "pure" component means that the render function only depends on props and state,
* which allows us to add performance optimizations (see `shouldComponentUpdate` below).
*/
class PureComponent<P, S> extends React.Component<P, S> {
shouldComponentUpdate(nextProps: P, nextState: S): boolean {
return !shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState);
}
}
interface UserNameProps {
user: User;
}
/**
* Renders the user's name with some markup
*/
class UserName extends PureComponent<UserNameProps, {}> {
render() {
return React.DOM.div({}, `User name is: ${user.name}`);
}
}
interface FetchUserWithRenderCallbackProps {
userId: UserId;
renderChild: (user: User) => React.ReactElement<any>;
}
/**
* Fetches the user and passes it to a render callback to render results.
*/
class FetchUserWithRenderCallback extends PureComponent<FetchUserWithRenderCallbackProps, {}> {
render() {
// This by-passes the react lifecycle, as the User is *not* passed in as a prop.
// If the user changes, the Child element will not have any props change. If
// using Pure components, this means the Child element will not re-render.
// https://medium.com/building-asana/designing-simpler-react-components-13a0061afd16#8bce
return this.props.renderChild(this._fetchUser());
}
private _fetchUser() {
// Fetch the user from the datastore, imagine this is a thing.
return datastore.fetchUser(userId);
}
}
interface FetchUserWithInjectionProps {
userId: UserId;
child: React.ReactElement<{ user: User }>;
}
/**
* Fetches the user and injects contents into the passed-in component.
*/
class FetchUserWithInjection extends PureComponent<FetchUserWithInjectionProps, {}> {
render() {
// This does not by-pass the react lifecycle, as the User *is* passed in as a prop.
// If the user changes, the Child element will have a props change. If
// using Pure components, this means the Child element will re-render.
return React.cloneElement(this.props.child, {
user: this._fetchUser()
});
}
private _fetchUser() {
// Fetch the user from the datastore, imagine this is a thing.
return datastore.fetchUser(userId);
}
}
/**
* A component that fetches data and renders the user's name.
* It does this twice, once with a render callback and once with injection.
*/
class FetchAndRenderUser extends PureComponent<{}, {}> {
render() {
// Fetch the user, and then render UserName with it, using a render callback.
const withRenderCallback = React.createElement(FetchUserWithRenderCallback, {
userId: new UserId("123"),
renderChild: (user: User) => React.createElement(UserName, { user: user })
});
// Fetch the user, and then render UserName with it, using injection.
const withInjection = React.createElement(FetchUserWithInjection, {
userId: new UserId("123"),
child: React.createElement(UserName, {
// The user is injected by the `FetchUserWithInjection` component.
user: null
});
});
return React.DOM.div({},
withRenderCallback,
withInjection
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment