Skip to content

Instantly share code, notes, and snippets.

@leoasis
Last active September 5, 2017 15:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leoasis/367b556688e1aa0fb21f9b4d966079d6 to your computer and use it in GitHub Desktop.
Save leoasis/367b556688e1aa0fb21f9b4d966079d6 to your computer and use it in GitHub Desktop.
React Patterns - Render callback
class Parent extends React.Component {
render() {
return <Child foo={bar => <div>Hello {bar}!</div>} />;
}
}
class Child extends React.Component {
// Do some complex stuff in the lifecycle...
render() {
if (someLogic) {
return <div>Nothing to do here!</div>;
} else {
return this.props.foo(this.state.barCalculatedSomehow);
}
}
}
class StuffList extends React.Component {
constructor() {
super();
this.state = {
loading: true,
error: null,
data: null
};
}
componentDidMount() {
fetch(`/user/${this.props.userId}/stuff`).then(
data => this.setState({ loading: false, data }),
error => this.setState({ loading: false, error })
);
}
render() {
if (this.state.loading) return <Loading />;
if (this.state.error) {
return <ErrorMessage error={this.state.error} />;
}
return (
<ul>
{this.data.map(thing => (
<li key={thing.id}>
<h2>{thing.name}</h2>
<p>{thing.text}</p>
</li>
))}
</ul>
);
}
}
// I want my render logic to happen somewhere,
// but I need access to `this.state.data` that now lives
// inside `FetchStuff`
<FetchStuff userId={this.props.userId} ... />
<FetchStuff
userId={this.props.userId}
renderData={data => (
<ul>
{data.map(thing => (
<li key={thing.id}>
<h2>{thing.name}</h2>
<p>{thing.text}</p>
</li>
))}
</ul>
)}
/>;
class FetchStuff extends React.Component {
constructor() {
super();
this.state = {
loading: true,
error: null,
data: null
};
}
componentDidMount() {
fetch(`/user/${this.props.userId}/stuff`).then(
data => this.setState({ loading: false, data }),
error => this.setState({ loading: false, error })
);
}
render() {
if (this.state.loading) return <Loading />;
if (this.state.error) {
return <ErrorScreen error={this.state.error} />;
}
return this.props.renderData(this.state.data);
}
}
<TooltipTrigger tooltipContent={<span>This is the tooltip</span>}>
<div>Hover me!</div>
</TooltipTrigger>;
class TooltipTrigger extends React.Component {
constructor() {
super();
this.state = { hovering: false };
}
handleMouseEnter = () => {
this.setState({ hovering: true });
};
handleMouseLeave = () => {
this.setState({ hovering: false });
};
render() {
return (
<div
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
style={{ position: "relative" }}
>
{this.props.children}
{this.state.hovering &&
<div
style={{
position: "absolute" /* plus some other styles to position the tooltip */
}}
>
<Tooltip>{this.props.tooltipContent}</Tooltip>
</div>}
</div>
);
}
}
<TooltipTrigger
tooltipContent={() => (
<span>Something very complex with {data.we.may.not.yet.have}</span>
)}
>
<div>Hover me!</div>
</TooltipTrigger>;
class TooltipTrigger extends React.Component {
// ...
render() {
return (
<div
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
style={{ position: "relative" }}
>
{this.props.children}
{this.state.hovering &&
<div
style={{
position: "absolute" /* plus some other styles to position the tooltip */
}}
>
<Tooltip>
{this.props.tooltipContent() /* Notice the change here! */}
</Tooltip>
</div>}
</div>
);
}
}
<Route path="/some/url" render={() => <h3>Hello.</h3>} />;
const ItemToMeasure = () => (
<Measure>
{dimensions => (
<div>
Some content here
<pre>
{JSON.stringify(dimensions, null, 2)}
</pre>
</div>
)}
</Measure>
);
class App extends React.Component {
render() {
return (
<div>
<Media query="(max-width: 599px)">
{matches =>
matches
? <p>The document is less than 600px wide.</p>
: <p>The document is at least 600px wide.</p>}
</Media>
</div>
);
}
}
<Motion defaultStyle={{ x: 0 }} style={{ x: spring(10) }}>
{value => <div>{value.x}</div>}
</Motion>;
<ListView
dataSource={this.state.dataSource}
renderRow={rowData => <Text>{rowData}</Text>}
/>;
class Greeter extends React.Component {
render() {
const { name } = this.props;
return (
<Clock
renderEverySecond={time => {
return <h1>Hello {name} - The time is {time.toString()}</h1>;
}}
/>
);
}
}
class Clock extends React.Component {
constructor() {
super();
this.state = { element: null };
}
componentDidMount() {
const { renderEverySecond } = this.props;
setInterval(
() => {
this.setState({
element: renderEverySecond(new Date())
});
},
1000
);
}
render() {
return this.state.element;
}
}
class Clock extends React.Component {
// ...
componentDidMount() {
setInterval(
() => {
this.setState({
element: this.props.renderEverySecond(new Date())
});
},
1000
);
}
}
class Greeter extends React.Component {
render() {
return (
<Clock
renderEverySecond={time => {
return (
<h1>Hello {this.props.name} - The time is {time.toString()}</h1>
);
}}
/>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment