Software Developer at
@HerrHerrmann
import * as _ from 'lodash';
const activeUsernames = _(users)
.filter({ isActive: true })
.map('username')
.sort()
.value();
const isMature = age => age > 17;
const getAge = user => user.profile.age;
import { map } from 'lodash/fp';
const getName = user => user.name;
const getNames = map(getName);
partial application
const userNames = getNames(users);
// ❌ mutability
const user = { name: 'Sarah' };
user.name = 'Buffy';
users.push(user);
// ✅ immutability
const user = { name: 'Sarah' };
const changedUser = { ...user, name: 'Buffy' };
const usersWithSarah = [ ...users, changedUser ];
// ❌ impure function
const getStateImpure = () => window.appState.name;
// ✅ pure function
const getState = currentWin => currentWin.appState.name;
// ✅ via lodash/fp
const getState = get('appState.name');
import * as _ from 'lodash';
const devNames = _(users)
.filter(isDeveloper)
.map(getName)
.value();
import { compose, filter, map, toUpper } from 'lodash/fp';
const getDevNames = compose(
map(getName),
filter(isDeveloper),
);
const devNames = getDevNames(users);
const getDevNamesUpper = compose(
toUpper,
getDevNames,
);
const multiplyByTwo = multiply(2);
map(multiplyByTwo, [1, 2, 3, 4]);
// => [2, 4, 6, 8]
const UserListPageWithData = withData(
{
users: api.loadUsers
},
UserListPage
);
// => UserListPage called with prop "users"
const getManagers =
users => users.filter(user => user.isManager);
const getNamesOfManagers =
users => getManagers(users).map(user => user.name);
// VS
const getManagers = filter(get('isManager'));
const getNamesOfManagers = compose(map(get('name')), getManagers);
// ^ pointfree functions!
import { compose } from 'lodash/fp';
import { mapProps, withState } from 'recompose';
import { withAppContext } from '../../hoc/withAppContext';
// "Plain" stateless component
const ReadMoreText = (/*...*/) => {/*...*/};
// Component with state and context
export default compose(
withAppContext,
withState('expanded', 'setExpanded', false),
mapProps(sanitizeText),
)(ReadMoreText);
export default compose(
withAppContext,
withData({
resolve: {
summaries: api.meetingSummaries.fetchSummaries,
},
}),
Component => props => (
<Component {...props}
summaries={map(createSummaryFromDto, props.summaries)}
/>
),
withLocalStorage('meetings-overview-page-view'),
withStore(undefined, mapDispatchToProps)
)(MeetingOverviewPage);
const CommentCountWithLoader = withData({
resolve: {
commentCountResponse:
({ objective }) => batchRequest(/* ... */)
},
pendingComponent: PendingCommentCount,
errorComponent: CommentCountError
})(CommentCount);
export default ifVisible({
pendingComponent: InvisibleCommentCount
})(CommentCountWithLoader);
Use FP as much as you like!
(But don't throw consistency overboard.)
Questions? Comments? Opinions?
Slides: bit.ly/fp-react
Costume by SHOXXX (www.shoxxxboxxx.com)