A component like this would be rejected in code review for having both a presentation and data concern:
// CommentList.js
import React from "react";
class CommentList extends React.Component {
constructor() {
super();
this.state = { comments: [] }
}
componentDidMount() {
fetch("/my-comments.json")
.then(res => res.json())
.then(comments => this.setState({ comments }))
}
render() {
return (
<ul>
{this.state.comments.map(({ body, author }) =>
<li>{body}-{author}</li>
)}
</ul>
);
}
}
It would then be split into two components. The first is like a traditional template, concerned only with presentation, and the second is tasked with fetching data and rendering the related view component.
// CommentList.js
import React from "react";
const Commentlist = comments => (
<ul>
{comments.map(({ body, author }) =>
<li>{body}-{author}</li>
)}
</ul>
)
// CommentListContainer.js
import React from "react";
import CommentList from "./CommentList";
class CommentListContainer extends React.Component {
constructor() {
super();
this.state = { comments: [] }
}
componentDidMount() {
fetch("/my-comments.json")
.then(res => res.json())
.then(comments => this.setState({ comments }))
}
render() {
return <CommentList comments={this.state.comments} />;
}
}
In the updated example, CommentListContainer could shed JSX pretty simply.
render() {
return React.createElement(CommentList, { comments: this.state.comments });
}
Additionally, a Higher-order Component or component with Render Props could help in making container components and stateless components more composeable