ffxsam
ffxsam

Reputation: 27713

Can I put AJAX calls in the presentational component, or should I extract a container?

I spend a lot of time thinking about how to best structure things as cleanly as possible in React. Lately I've been getting hung up on whether React containers should do nothing but connect to Redux (or other data - a la Meteor) and render/return a single component, or if containers should also be in charge of event-handling as well. So for example, it's a toss-up between these two models:

Model 1

// ThingContainer.js

import Thing from '../components/Thing';
export default someHigherOrderFunc(/* map state/data to props */)(Thing)

// Thing.js

export default class Thing extends Component {
  handleClick() { /* ... */ }
  handleMouseEnter() { /* ... */ }
  render() {
    // Other components rendered here, both container or presentational
  }
}

Model 2

// ThingContainer.js

class ThingContainer extends Component {
  handleClick() { /* ... */ }
  handleMouseEnter() { /* ... */ }
  render() {
    // Now Thing can be stateless
    return <Thing 
      onClick={this.handleClick}
      onMouseEnter={this.handleMouseEnter}
    />
  }
}

export default someHigherOrderFunc()(ThingContainer)

It almost feels like in model 1, Thing becomes its own container in a sense, which I'm not sure I like. Model 2 feels more natural, as ThingContainer is charged with not just dealing with data and Redux, but also handling events, firing off Ajax requests in componentDidMount, etc. With the first model, if I wanted an Ajax request to be invoked in componentDidMount, it would have to go in Thing which doesn't seem right.

I'm wondering if there are any particular advantages or pitfalls to either of these approaches, or if it just comes down to style/preference.

Upvotes: 13

Views: 1659

Answers (1)

Dan Abramov
Dan Abramov

Reputation: 268255

There is nothing inherently wrong with doing AJAX inside the “presentational-ish” Thing when it’s only a couple of methods, and this component is never used in different scenarios anyway. Don’t split behavior from presentation before you’re sure how the behavior changes in different contexts.

That you have this dilemma means your component doesn’t need to be reused yet. In this case it doesn’t matter how you split it. Both ways work fine so I’d go for the simpler one (model 1).

Later you may realize that you want to reuse the same look-n-feel but trigger different AJAX calls, or compute the props differently. At this point you may want to remove the event handling from Thing and create several different ThingContainers, each handling events and computing props a little bit differently. This is when separating presentation and behavior becomes useful.

Upvotes: 16

Related Questions