Learn how to pass store down as a prop to container components instead of declaring a top-level variable to prepare for easier testing and server rendered applications.
[00:00] In the previous lessons, we used this tool to up level variable to refer to the Redux chore. The components that access this chore, such as the container components, read this straight from it, subscribe to this chore, and dispatch actions on this chore using this chore top-level variable.
[00:20] This approach works fine for JS bin example where everything is in a single file. However, it doesn't scale to real applications for several reasons.
[00:30] First of all, it makes your container components harder to test because they reference a specific chore, but you might want to supply a different marks chore in the test. Secondly, it makes it very hard to implement universal replications that are rendered on the server, because on the server, you want to supply a different chore instance for every request because different requests have different data.
[00:57] I'm going to start by moving this chore creation code to the bottom of the file where I render my React components. I'm going to change it slightly. Instead of creating this chore top-level variable, I will pass this chore I create as a prop to the top-level component, so it is completely injectable into it.
[01:21] Every container component needs a reference to this chore so unfortunately, we have to pass it down to every component as a prop. It's less effort than passing different data through every component, but it's still inconvenient. So, don't worry, we'll find a better solution later, but for now, we need to see the problem.
[01:41] The problem is that the container components need to have this chore instance to get this straight from a dispatch actions and subscribe to the changes. This time, I'm changing the container component to take this chore from the props using the ES6 destruction syntax, which just means "chore equals props does chore."
[02:02] I'm doing the same here. I'm just taking this chore from the props so I can call dispatch on it.
[02:09] I need to make similar changes to other container components. In this case, I have this at to-do component, which is not exactly a container component, but it still needs its chore to dispatch the at to-do action, so I added it as a prop. I'm also going to add this chore to the photo component because, unfortunately, filter link needs it.
[02:32] The photo component renders filter link. This is not convenient, but as I said, we'll figure out a way to avoid this later. For now, we need to pass this chore down so that every container component, such as filter link, can use it to subscribe to the changes, to read this state and to dispatch actions without relying on a top-level variable being available.
[02:57] I'm changing the render method to read this chore from the props. Now, all containers read this chore instance from the props, and don't rely on a top-level variable that I removed.
[03:09] Note that this change did not change the behavior or the data flow of this application. The container components subscribe to this chore, just like before, and update their state in response to its changes.
[03:24] However, what changed is how they access this chore. Previously, they would access a top-level variable, but this approach does not scale to real-world applications. This is why, right now, I'm passing down this chore as a prop, so the container components can subscribe to it.
[03:44] In the future lessons, we will see how to pass this chore down to the container components implicitly but without introducing the top-level variable.
Yes, this would be a performance concern. You can hand write optimizations in the container components, or you can use connect()
from next lessons that does that for you.
Thanks for replying. So connect automatically determines which part of the state tree to pass down? Or more specifically, the part of the state that gets applied to the props in connect is the only part that is subscribed to?
The components generated by connect()
behave very similarly to those I wrote by hand, but they use setState()
instead of forceUpdate()
and implement a performant shouldComponentUpdate()
optimization which skips rendering if the part of the state selected by mapStateToProps()
has not changed.
Thanks! Thanks for the great tutorial.
Is it a concern that some components are subscribing to the whole store without using all of the elements in the store? For instance, the Footer is going to ForceUpdate every time a new todo item is added correct? Is this OK because React won't actually trigger an update of the child component because it's props didn't change? Can this cause performance issues if lots of items are being displayed like you mention in your SO answer here?