Learn how to use the 'compose' function to mix together HOCs, even ones from other libraries like 'connect' from redux.
[00:00] What if we're in a situation where we want to use multiple higher order components on the same component? For example, I'm pulling in two higher order components from Recompose, setDisplayName and setPropTypes, and I'm also pulling in connect from Redux. I'd like to use all three on this user.
[00:17] I could do it like this, setDisplayName to user, and then I could wrap it like so. Then I'd have to wrap that in setPropTypes, and pass in the config for that, which I won't fill out right now, because I'm just trying to illustrate a point.
[00:42] I have to put another closing thing out here. Then I could do finally my connecting, which I could put my config in there as well, but I'll just do a regular connect. Again, I'd have to wrap it like that.
[00:56] Obviously, you get this nesting effect that we don't want, so I'm going to undo everything. Instead, what would actually be better is if we could just compose these three higher order components together into one. There's definitely a method for that, that Recompose provides.
[01:16] It works like any other compose method found in functional libraries, typically. Let's go ahead and make a single higher-order component out of these three.
[01:27] We just call compose, I like to kind of split them across lines like this, and then we're going to use each one on its own line. I'm going to set the display name to user, I'm going to set the prop types on this thing to a name is react.propTypes.string, and I'm going to make that required.
[01:56] Also I need to set status, is react.propTypes.string, and that doesn't have to be required. Then finally, I'd like to connect this component. I'm just going to a regular connect here, I'm not going to pass in any map state to props, or map dispatch to props.
[02:15] Now we have our enhance. We can use our single higher-order component and wrap our functional stateless component, and now it's enhanced with all the goodies. I'm actually using a faked out version of Redux's connect, every time a dispatch happens, it's just going to console log out the action.
[02:37] We have to add an onClick here. We're going to call dispatch, and we're going to dispatch an action that has a type of -- yeah, let's use userSelected. Because we used the connect higher order component, that actually provides us dispatch as a prop, and that's how we got the ability to dispatch here.
[03:04] Just for showing how that the setDisplayName worked, I'm going to console log out user.DisplayName. OK, let's do that. We will open up the console, we're going to refresh.
[03:20] Every time I click you can see that we're dispatching user selected, and you can see our display name was logged out. Yeah, if we don't pass in, for example, maybe one of these things, we'll get an error because our propTypes, the prop-name is marked as required in user, but its value is undefined. So all of our higher order components are working, just merged into one.
To be precise you should have
const enhance = compose( connect(), setPropTypes({ name: React.PropTypes.string.isRequired, status: React.PropTypes.string }), setDisplayName('User') );
The order of execution in compose is reverse
Did the dispatch prop being initialized in connect and pass on implicitly?
Would love to see some coverage of the Obeservables HOCs from Recompose :)
I notice the use of the setPropTypes within one of the HOCs. How could I integrate flow typing instead of propTypes to such a HOC?