React Patterns - Render callback
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> | |
); | |
} | |
} |
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); | |
} | |
} |
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> | |
); | |
} | |
} |
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> | |
); | |
} | |
} |
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; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment