-1

What's the difference between A) using the connect method of connecting state and dispatch function to a component and B) simply having functions in a component that do the dispatching as well as accessing the store as a global directly?

(Not ES2015)

Andy
  • 1,452
  • 1
  • 13
  • 18

1 Answers1

2

Quoting from the Redux FAQ on importing the store directly:

While you can reference your store instance by importing it directly, this is not a recommended pattern in Redux. If you create a store instance and export it from a module, it will become a singleton. This means it will be harder to isolate a Redux app as a component of a larger app, if this is ever necessary, or to enable server rendering, because on the server you want to create separate store instances for every request.

I also recently wrote a Reddit comment on why you should use React-Redux and connect instead of talking to the store directly. Quoting that:

First, while you can manually write the code to subscribe to the Redux store in your React components, there's absolutely no reason to write that code yourself. The wrapper components generated by React-Redux's connect function already have that store subscription logic taken care of for you.

Second, connect does a lot of work to ensure that your actual components only re-render when they actually need to. That includes lots of memoization work, and comparisons against the props from the parent component and the values returned by your mapStateToProps function for that component. By not using connect, you're giving up all those performance improvements, and your components will be unnecessarily re-rendering all the time.

Third, by only connecting your top-level component, you are also causing the rest of your app to re-render unnecessarily. The best performance pattern is to connect lots of components in your app, with each connected component only extracting the pieces of data it actually needs via mapStateToProps. That way, if any other data changes, that component won't re-render.

Fourth, you're manually importing the store into your components, and directly coupling them together, thus making it harder to test the components. I personally try to keep my components "unaware" of Redux. They never reference props.dispatch, but rather call pre-bound action creators like this.props.someFunction(). The component doesn't "know" that it's a Redux action creator - that function could be a callback from a parent component, a bound-up Redux action creator, or a mock function in a test, thus making the component more reusable and testable.

And finally, the vast majority of apps built using React and Redux use the React-Redux library. It's the official way to bind the two together, and doing anything else will just confuse other developers looking at your project.

For more info, see:

Source: I'm a Redux maintainer, and author of the Redux FAQ.

Community
  • 1
  • 1
markerikson
  • 63,178
  • 10
  • 141
  • 157
  • What subscription logic are you referring to? I was under the impression that you only need to use store.subscribe() to re-render the root component every time something changes. – Andy Jun 21 '17 at 18:11
  • Per my comment, while you _can_ only have the root component subscribe to the Redux store, it's usually better for performance and maintainability if _many_ components are subscribed to the store. For example, instead of just having a connected TodoList, you might want to all of its list item components be connected too (per the example I give in that Reddit thread). But, even with only one component connected, there's no reason for _you_ to write that subscription logic - `connect()` already does it for you. – markerikson Jun 21 '17 at 18:16
  • The reason why someone might want to write that subscription logic themselves is to avoid using connect(), which requires you to write the mapToProps code (which is more things to write). Anyway, the "maintainability" benefit is opinionated, but can you explain the "performance" benefit? – Andy Jun 21 '17 at 18:28
  • Uh... if you call `store.subscribe()` yourself, you'll be writing at _least_ that much code to extract the right data for that component, _plus_ all the store subscription logic. That's _more_ code than just using `connect()`. For performance, again per my comments and linked discussions, `connect()` already implements memoization and equality checks to ensure your wrapped component only re-renders when incoming props or extracted store data have actually changed. Please go read those linked articles and discussions :) – markerikson Jun 21 '17 at 18:30
  • It's also worth noting that `connect()` has an object shorthand syntax for binding action creators: `export default connect(mapState, {addTodo, toggleTodo})(TodoList)`, so you don't need to actually write a separate `mapDispatchToProps` function. So, you just write a `mapStateToProps` function to extract the state the component needs, and pass that and your component to `connect`. Very simple, and definitely not much code. – markerikson Jun 21 '17 at 18:34
  • But that's my question to begin with, why do you need to "extract the right data" when you can just access the store as a global variable? (given that I'm fine with using global variable and that I'm not using ES2015) I'll look into the articles, but I think the "re-render" you're talking about is the virtual DOM render not the actual DOM render right? – Andy Jun 21 '17 at 18:36
  • React's default behavior is to re-render the entire component tree (which yes, is a VDOM render). If only one small piece of data changed, then most of that re-rendering and VDOM diffing is wasted effort, so you want to skip re-rendering for components whose data hasn't changed. Again, the articles and discussions I linked discuss this in detail - please read them! – markerikson Jun 21 '17 at 18:39