id | sidebar_label | title | description | keywords | version | image | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
container-component |
Container component (Stateful component) |
Container Component (Stateful Component) |
Container component (Stateful component) | React Patterns, techniques, tips and tricks in development for Ract developer. |
|
Container component (Stateful component) |
/img/reactpatterns-cover.png |
A container does data fetching and then renders its corresponding sub-component.
Assume that you have a component that displays comments, you didn't know about container components, so you put everything in one place.
const fetchSomeComments = cb =>
cb([
{ author: "Bunlong VAN", body: "Nice to see you here!" },
{ author: "You", body: "Thanks!" }
])
class CommentList extends React.Component {
this.state = { comments: [] }
componentDidMount() {
fetchSomeComments(comments => this.setState({ comments: comments }))
}
render() {
return (
<ul>
{this.state.comments.map(c => (
<li>{c.body}—{c.author}</li>
))}
</ul>
)
}
}
ReactDOM.render(
<CommentList />,
document.getElementById("root")
)
Your component is responsible for both fetching data and presenting it. There's nothing wrong with this but you miss out on a few benefits of React.
CommentList
can't be reused unless under the exact same circumstances.
Lets pull out data-fetching into a container component.
class CommentListContainer extends React.Component {
state = { comments: [] }
componentDidMount() {
fetchSomeComments(comments =>
this.setState({ comments: comments }))
}
render() {
return <CommentList comments={this.state.comments} />
}
}
Now, let's rework CommentList
to take comments as a prop.
const CommentList = props =>
<ul>
{props.comments.map(c => (
<li>{c.body}—{c.author}</li>
))}
</ul>
What we got:
- Separated our data-fetching and rendering concerns
- Made our
CommentList
component reusable - Given
CommentList
the ability to set PropTypes