Enter Your Email Address to Watch This Lesson

Your link to unlock this lesson will be sent to this email address.

Unlock this lesson and all 1083 of the free egghead.io lessons, plus get React content delivered directly to your inbox!



Existing egghead members will not see this. Sign in.

Transform Props by using the Recompose mapProps Higher Order Component

2:49 React lesson by

Learn how to use the 'mapProps' higher-order component to modify an existing component’s API (its props). 'mapProps' takes incoming props and changes them however you’d like; for example, filtering the props by a field.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

Learn how to use the 'mapProps' higher-order component to modify an existing component’s API (its props). 'mapProps' takes incoming props and changes them however you’d like; for example, filtering the props by a field.

I'm displaying three UserLists. They're filtered by status.

Users

These are my active users, inactive, and pending. I'm doing it by using a simple UserList component that I wrote, and filtering the users' array based on the status.

const App = () =>
    <div className="App">
        <h3>active users</h3>
        <UserList users={ users.filter(u => u.status === 'active') } />

        <h3>inactive users</h3>
        <UserList users={ users.filter(u => u.status === 'inactive') } />        

        <h3>pending users</h3>
        <UserList users={ users.filter(u => u.status === 'pending') } />        
    </div>

I'd like to replace this block of code. I want to hide away the custom filtering logic into some custom components. Instead, we'll have three components. We'll have ActiveUsers. I just want to pass it to users and have it figure out which ones are active. We'll have InactiveUsers, and we'll have PendingUsers.

const App = () => 
    <div className="App">
        <ActiveUsers users={ users } />
        <InactiveUsers users={ users } />
        <PendingUsers users={ users } />
    </div>

I'll create ActiveUsers by calling a higher-order component called filterByStatus. I'm going to tell it I want to filter by the 'active' status and I'll pass it my UserList, which is the base component that I want to modify. I'll do the same thing for InactiveUsers and PendingUsers.

const ActiveUsers = filterByStatus('active')(UserList);
const InactiveUsers = filterByStatus('inactive')(UserList);
const PendingUsers = filterByStatus('pending')(UserList);

Now, let's implement filterByStatus. filterByStatus needs to take in a status, and it needs to return a higher-order component. I'm going to make use of the mapProps higher-order component from Recompose.

mapProps takes in a function. That function takes in the props. We'll take some props in and we'll map them to some new props. The only prop I care to look at is the users prop.

const filterByStatus = {status} => mapProps(
    ({ users })
);

I want to return an object, which will be the new prop object. mapProps completely blows away any props passed in. If they're not in this object, they won't be passed to the wrapped component.

const filterByStatus = {status} => mapProps(
    ({ users }) => ({

    })
);

I want to pass in status and I want to pass in a new users prop. This one will take the users prop coming in, but filter it the same way we were doing before. I'll check if it's equal to the status that I supply.

const filterByStatus = {status} => mapProps(
    ({ users }) => ({
        status, 
        users: users.filter(u => u.status === status)
    })
);

UserList now gets the filtered users and the status. I want to add the header into my component. I'll use the status and the word users to create my header. When I refresh, everything continues to behave the same.

const UserList = ({ users, status }) => 
    <div className="UserList">
        <h3>{ status } users</h3>
        { users && users.map((user) => <User {...user} />) }
    </div>;

If I were to change one of the user's statuses, you'll see the filtering logic continues to work.

Filtering Works



HEY, QUICK QUESTION!
Joel's Head
Why are we asking?