Skip to content

Instantly share code, notes, and snippets.

@chantastic
Last active May 13, 2025 12:04
Show Gist options
  • Save chantastic/fc9e3853464dffdb1e3c to your computer and use it in GitHub Desktop.
Save chantastic/fc9e3853464dffdb1e3c to your computer and use it in GitHub Desktop.

Revisions

  1. chantastic revised this gist Sep 12, 2017. 2 changed files with 34 additions and 40 deletions.
    68 changes: 31 additions & 37 deletions on-jsx.markdown
    Original file line number Diff line number Diff line change
    @@ -1,36 +1,35 @@
    Hi Nicholas,

    I saw you tweet about JSX yesterday. It seemed like the discussion devolved pretty quickly but I wanted to share our experience over the last year. I understand your concerns. I've made [similar remarks about JSX](https://twitter.com/chantastic/status/477322739120750592). When we started using it Planning Center, I lead the charge to write React without it. I don't imagine I'd have much to say that you haven't considered but, if it's helpful, here's a pattern that changed my opinion:
    I saw you tweet about JSX yesterday. It seemed like the discussion devolved pretty quickly but I wanted to share our experience over the last year. I understand your concerns. I've made [similar remarks about JSX](https://twitter.com/chantastic/status/477322739120750592). When we started using it Planning Center, I led the charge to write React without it. I don't imagine I'd have much to say that you haven't considered but, if it's helpful, here's a pattern that changed my opinion:

    The idea that "React is the V in MVC" is disingenuous. It's a good pitch but, for many of us, it feels like in invitation to repeat our history of coupled views. In practice, React is the V and the C. [Dan Abramov](https://twitter.com/dan_abramov) describes the division as [Smart and Dumb Components](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0). At our office, we call them *stateless* and *container* components (*view-controllers* if we're Flux). The idea is pretty simple: components can't be concerned with both presentation and data-fetching. I feel like an example might be clearer...

    A component like this would be rejected in code review for having *both a presentation and data concern*:

    ```javascript
    // CommentList.js
    import React from "react";

    class CommentList extends React.Component {
    constructor(props) {
    super(props);
    constructor() {
    super();
    this.state = { comments: [] }
    }

    componentDidMount() {
    $.ajax({
    url: "/my-comments.json",
    dataType: 'json',
    success: function(comments) {
    this.setState({comments: comments});
    }.bind(this)
    });
    fetch("/my-comments.json")
    .then(res => res.json())
    .then(comments => this.setState({ comments }))
    }

    render() {
    return <ul> {this.state.comments.map(renderComment)} </ul>;
    }

    renderComment({body, author}) {
    return <li>{body}—{author}</li>;
    return (
    <ul>
    {this.state.comments.map(({ body, author }) =>
    <li>{body}-{author}</li>
    )}
    </ul>
    );
    }
    }
    ```
    @@ -39,24 +38,21 @@ It would then be split into two components. The first is like a traditional temp

    ```javascript
    // CommentList.js

    class CommentList extends React.Component {
    constructor(props) {
    super(props);
    }

    render() {
    return <ul> {this.props.comments.map(renderComment)} </ul>;
    }

    renderComment({body, author}) {
    return <li>{body}—{author}</li>;
    }
    }
    import React from "react";

    const Commentlist = comments => (
    <ul>
    {comments.map(({ body, author }) =>
    <li>{body}-{author}</li>
    )}
    </ul>
    )
    ```

    ```javascript
    // CommentListContainer.js
    import React from "react";
    import CommentList from "./CommentList";

    class CommentListContainer extends React.Component {
    constructor() {
    @@ -65,13 +61,9 @@ class CommentListContainer extends React.Component {
    }

    componentDidMount() {
    $.ajax({
    url: "/my-comments.json",
    dataType: 'json',
    success: function(comments) {
    this.setState({comments: comments});
    }.bind(this)
    });
    fetch("/my-comments.json")
    .then(res => res.json())
    .then(comments => this.setState({ comments }))
    }

    render() {
    @@ -88,11 +80,13 @@ In the updated example, *CommentListContainer* could shed JSX pretty simply.
    }
    ```

    Additionally, a [Higher-order Component](http://reactpatterns.com/#higher-order-component) or component with [Render Props](http://reactpatterns.com/#render-callback) could help in making container components and stateless components more composeable

    ### What does this have to do with disliking JSX?

    When we started doing this, concerns about JSX vanished. Writing "dumb components" feels just the same as Handlebars or ERB templates but with the full power of JavaScript. We realized that it wasn't JSX that bothered us as much as the nagging feeling that components were just smaller balls of mud. For a while, our components were just smaller balls of mud but this pattern helped break the cycle.

    I hope that this was a helpful addition to the conversation. I've written about it in slightly more detail [here](https://medium.com/@learnreact/container-components-c0e67432e005). You can also see Jason Bota's [talk about how they do this at Facebook](https://www.youtube.com/watch?v=KYzlpRvWZ6c&t=1351).
    I hope that this was a helpful addition to the conversation. I've written about it in slightly more detail [here](https://medium.com/@learnreact/container-components-c0e67432e005) and [here](http://reactpatterns.com/#container-component). You can also see Jason Bota's [talk about how they do this at Facebook](https://www.youtube.com/watch?v=KYzlpRvWZ6c&t=1351).

    Cheers!

    6 changes: 3 additions & 3 deletions on-this-gist.markdown
    Original file line number Diff line number Diff line change
    @@ -10,9 +10,9 @@ So it shouldn't look as foreign to newcomers.

    If you'd like more up-to-date React recourses, I mantain these sites:

    [learnreact.com](https://learnreact.com)
    [reactpatterns.com](http://reactpatterns.com)
    [reactcheatsheet.com](https://reactcheatsheet.com)
    [learnreact.com](https://learnreact.com)
    [reactpatterns.com](http://reactpatterns.com)
    [reactcheatsheet.com](https://reactcheatsheet.com)

    These resources are more closely monitored and updated.

  2. chantastic revised this gist Sep 12, 2017. 1 changed file with 21 additions and 0 deletions.
    21 changes: 21 additions & 0 deletions on-this-gist.markdown
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,21 @@
    Hi Everyone else 👋

    You likely got here from a very popular article by Dan Abramov on the topic of container components.

    I'm surprised by the ammount of attention this resource has recieved as it's just an extension of a Twitter conversation I was having.

    Gists are a terrible medium because I don't get notified on comments.
    I've taken a little time today to modernize the code example.
    So it shouldn't look as foreign to newcomers.

    If you'd like more up-to-date React recourses, I mantain these sites:

    [learnreact.com](https://learnreact.com)
    [reactpatterns.com](http://reactpatterns.com)
    [reactcheatsheet.com](https://reactcheatsheet.com)

    These resources are more closely monitored and updated.

    Thanks for the support!

    💖 @chantastic
  3. chantastic revised this gist May 4, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion on-jsx.markdown
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    Hi Nicholas,

    I saw you tweet about JSX yesterday. It seemed like the discussion devolved pretty quickly but I wanted to share our experienc over the last year. I understand your concerns. I've made [similar remarks about JSX](https://twitter.com/chantastic/status/477322739120750592). When we started using it Planning Center, I lead the charge to write React without it. I don't imagine I'd have much to say that you haven't considered but, if it's helpful, here's a pattern that changed my opinion:
    I saw you tweet about JSX yesterday. It seemed like the discussion devolved pretty quickly but I wanted to share our experience over the last year. I understand your concerns. I've made [similar remarks about JSX](https://twitter.com/chantastic/status/477322739120750592). When we started using it Planning Center, I lead the charge to write React without it. I don't imagine I'd have much to say that you haven't considered but, if it's helpful, here's a pattern that changed my opinion:

    The idea that "React is the V in MVC" is disingenuous. It's a good pitch but, for many of us, it feels like in invitation to repeat our history of coupled views. In practice, React is the V and the C. [Dan Abramov](https://twitter.com/dan_abramov) describes the division as [Smart and Dumb Components](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0). At our office, we call them *stateless* and *container* components (*view-controllers* if we're Flux). The idea is pretty simple: components can't be concerned with both presentation and data-fetching. I feel like an example might be clearer...

  4. chantastic revised this gist May 4, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion on-jsx.markdown
    Original file line number Diff line number Diff line change
    @@ -90,7 +90,7 @@ In the updated example, *CommentListContainer* could shed JSX pretty simply.

    ### What does this have to do with disliking JSX?

    When we started doing this, concerns about JSX vanished. Writing "dumb components" feels just the same as Handlebars or ERB templates but with the full power of JavaScritp. We realized that it wasn't JSX that bothered us as much as the nagging feeling that components were just smaller balls of mud. For a while, our components were just smaller balls of mud but this pattern helped break the cycle.
    When we started doing this, concerns about JSX vanished. Writing "dumb components" feels just the same as Handlebars or ERB templates but with the full power of JavaScript. We realized that it wasn't JSX that bothered us as much as the nagging feeling that components were just smaller balls of mud. For a while, our components were just smaller balls of mud but this pattern helped break the cycle.

    I hope that this was a helpful addition to the conversation. I've written about it in slightly more detail [here](https://medium.com/@learnreact/container-components-c0e67432e005). You can also see Jason Bota's [talk about how they do this at Facebook](https://www.youtube.com/watch?v=KYzlpRvWZ6c&t=1351).

  5. chantastic revised this gist May 4, 2015. 1 changed file with 12 additions and 10 deletions.
    22 changes: 12 additions & 10 deletions on-jsx.markdown
    Original file line number Diff line number Diff line change
    @@ -1,17 +1,17 @@
    Hi Nicholas,

    I can't imagine that I'd have much to say on JSX that you haven't considered. You've written a book I've read several times and this is absotely the first you've heard of me. But I think we share a [similar and immediate rejection of JSX](https://twitter.com/chantastic/status/477322739120750592).
    I saw you tweet about JSX yesterday. It seemed like the discussion devolved pretty quickly but I wanted to share our experienc over the last year. I understand your concerns. I've made [similar remarks about JSX](https://twitter.com/chantastic/status/477322739120750592). When we started using it Planning Center, I lead the charge to write React without it. I don't imagine I'd have much to say that you haven't considered but, if it's helpful, here's a pattern that changed my opinion:

    The idea that "React is the V in MVC" is disingenuous. It's a good pitch but, for many of us, it feels like in invitation to repeat our history of coupled views. In practice, React is the V and the C. [Dan Abramov](https://twitter.com/dan_abramov) describes the division as [Smart and Dumb Components](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0). At our office, we call them *stateless* and *container* components (*view-controllers* when using Flux). The idea is pretty simple: components can't be concerned with both presentation and fetching data. I feel like an example might be easier...
    The idea that "React is the V in MVC" is disingenuous. It's a good pitch but, for many of us, it feels like in invitation to repeat our history of coupled views. In practice, React is the V and the C. [Dan Abramov](https://twitter.com/dan_abramov) describes the division as [Smart and Dumb Components](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0). At our office, we call them *stateless* and *container* components (*view-controllers* if we're Flux). The idea is pretty simple: components can't be concerned with both presentation and data-fetching. I feel like an example might be clearer...

    A component like this would be rejected in code review for having *both a presentation and data concern*:

    ```javascript
    // CommentList.js

    class CommentList extends React.Component {
    constructor() {
    super();
    constructor(props) {
    super(props);
    this.state = { comments: [] }
    }

    @@ -35,7 +35,7 @@ class CommentList extends React.Component {
    }
    ```

    It would then be split into two components. The first is like a traditional template, concerned only with presentation, and the second is concerned only with fetching data and rendering the related view.
    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.

    ```javascript
    // CommentList.js
    @@ -83,15 +83,17 @@ class CommentListContainer extends React.Component {
    In the updated example, *CommentListContainer* could shed JSX pretty simply.

    ```javascript
    render() {
    return React.createElement(CommentList, { comments: this.state.comments });
    }
    render() {
    return React.createElement(CommentList, { comments: this.state.comments });
    }
    ```

    ### What does this have to do with disliking JSX?

    When we started doing this, concerns about JSX vanished. We found that we weren't concerned about JSX, we were worried about components that were nothing more than smaller balls of mud. For a while, our components were just smaller balls of mud. But this pattern helped us break that cycle.
    When we started doing this, concerns about JSX vanished. Writing "dumb components" feels just the same as Handlebars or ERB templates but with the full power of JavaScritp. We realized that it wasn't JSX that bothered us as much as the nagging feeling that components were just smaller balls of mud. For a while, our components were just smaller balls of mud but this pattern helped break the cycle.

    I hope that this was a helpful addition to the conversation. I've written about it in slightly more detail [here](https://medium.com/@learnreact/container-components-c0e67432e005). You can also see Jason Bota's [talk about how they do this at Facebook](https://www.youtube.com/watch?v=KYzlpRvWZ6c&t=1351).

    Cheers!
    Cheers!

    Michael
  6. chantastic revised this gist May 4, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions on-jsx.markdown
    Original file line number Diff line number Diff line change
    @@ -55,7 +55,7 @@ class CommentList extends React.Component {
    }
    ```

    ```
    ```javascript
    // CommentListContainer.js

    class CommentListContainer extends React.Component {
    @@ -82,7 +82,7 @@ class CommentListContainer extends React.Component {

    In the updated example, *CommentListContainer* could shed JSX pretty simply.

    ```
    ```javascript
    render() {
    return React.createElement(CommentList, { comments: this.state.comments });
    }
  7. chantastic revised this gist May 4, 2015. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions on-jsx.markdown
    Original file line number Diff line number Diff line change
    @@ -53,7 +53,9 @@ class CommentList extends React.Component {
    return <li>{body}—{author}</li>;
    }
    }
    ```

    ```
    // CommentListContainer.js
    class CommentListContainer extends React.Component {
  8. chantastic created this gist May 4, 2015.
    95 changes: 95 additions & 0 deletions on-jsx.markdown
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,95 @@
    Hi Nicholas,

    I can't imagine that I'd have much to say on JSX that you haven't considered. You've written a book I've read several times and this is absotely the first you've heard of me. But I think we share a [similar and immediate rejection of JSX](https://twitter.com/chantastic/status/477322739120750592).

    The idea that "React is the V in MVC" is disingenuous. It's a good pitch but, for many of us, it feels like in invitation to repeat our history of coupled views. In practice, React is the V and the C. [Dan Abramov](https://twitter.com/dan_abramov) describes the division as [Smart and Dumb Components](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0). At our office, we call them *stateless* and *container* components (*view-controllers* when using Flux). The idea is pretty simple: components can't be concerned with both presentation and fetching data. I feel like an example might be easier...

    A component like this would be rejected in code review for having *both a presentation and data concern*:

    ```javascript
    // CommentList.js

    class CommentList extends React.Component {
    constructor() {
    super();
    this.state = { comments: [] }
    }

    componentDidMount() {
    $.ajax({
    url: "/my-comments.json",
    dataType: 'json',
    success: function(comments) {
    this.setState({comments: comments});
    }.bind(this)
    });
    }

    render() {
    return <ul> {this.state.comments.map(renderComment)} </ul>;
    }

    renderComment({body, author}) {
    return <li>{body}—{author}</li>;
    }
    }
    ```

    It would then be split into two components. The first is like a traditional template, concerned only with presentation, and the second is concerned only with fetching data and rendering the related view.

    ```javascript
    // CommentList.js

    class CommentList extends React.Component {
    constructor(props) {
    super(props);
    }

    render() {
    return <ul> {this.props.comments.map(renderComment)} </ul>;
    }

    renderComment({body, author}) {
    return <li>{body}—{author}</li>;
    }
    }

    // CommentListContainer.js

    class CommentListContainer extends React.Component {
    constructor() {
    super();
    this.state = { comments: [] }
    }

    componentDidMount() {
    $.ajax({
    url: "/my-comments.json",
    dataType: 'json',
    success: function(comments) {
    this.setState({comments: comments});
    }.bind(this)
    });
    }

    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 });
    }
    ```

    ### What does this have to do with disliking JSX?

    When we started doing this, concerns about JSX vanished. We found that we weren't concerned about JSX, we were worried about components that were nothing more than smaller balls of mud. For a while, our components were just smaller balls of mud. But this pattern helped us break that cycle.

    I hope that this was a helpful addition to the conversation. I've written about it in slightly more detail [here](https://medium.com/@learnreact/container-components-c0e67432e005). You can also see Jason Bota's [talk about how they do this at Facebook](https://www.youtube.com/watch?v=KYzlpRvWZ6c&t=1351).

    Cheers!