I have a withUserData higher-order component that's fetching user data and supplying it to my user list. If there is an error, it'll set the state with an error. If it's successful, it sets the state with the successful user data. Either way, this gets converted to props passed into my user list. I either receive users or error.
When everything's fine, it shows the user list as normal, but if I have an error, and the status code is available, I want to show an auth error. If there's no error, but the user length is equal to zero, I want to show a "No users" message.
Let's create a new higher-order component. We'll compose together a couple of things. First, we'll use withUserData, and then we'll use branch to render the auth error if the data has an error code.
The first parameter is a predicate that returns true or false. The component we want to render is going to be the auth error. Let's implement hasErrorCode.
Branch's predicate always gets passed to props, so I'm going to remove this logic and put it here. Then I'll actually destructure error off of the props, and I'll further remove the rest of this logic.
Now let's show the "No users" message when the data has no users. We'll call renderComponent and pass it the "No user" message. Let's implement the noUsers predicate. I'll steal this logic right here, and move it over to here, and remove this line completely.
You can see our user list has been cleaned up immensely. It's now dealing with happy-path-only scenarios. All of our non-optimal states have been moved out and dealt with separately. Now we have to use our new higher-order component here.
We should be able to refresh and still see the same behavior. I can return different responses, such as an unauthenticated error, and see that we're unauthenticated, or I can return an empty array and show a message.
If you wanted to go even further, we could refactor this even more. Let's replace this with a custom higher-order component called nonOptimalStates. I'd like to be able to just pass an array of objects. I want to say when hasErrorCode render authError, and when hasNoUsers render the "No users" message.
This will come in handy across my application when dealing with all the non-optimal states for all of my components. Now we have to implement that.
It's going to take in a state's array, and it's got to return our higher-order component, because that's what compose is looking for. Because I'm going to have multiple calls to branch, I'm going to have to wrap them all in a compose call themselves. I'm actually going to return a composed higher-order component.
I want to map over the states array. I'll take each state in, and I'll return a branched higher-order component. The predicate will be the state's when key. I'll render the state's render key. When I map over the states, that will return an array, but compose is expecting ordinal parameters, so I need to spread those in.
I should be able to refresh and see the same behavior as before. Again, I can comment out different things, and return either errors, or maybe no users, and it behaves the same.