Reduce code size by ~27% (99 -> 72 LOC)
Object.assign calls from 8 down to 2
Smell #1: Call another reducer with a new action
const movies = (state = {}, action) => {
switch(action.type) {
case 'ADD_MOVIES_VIA_OBJECTS':
return Object.assign({}, state, action.movies.
reduce((movies, movieObject) => (
Object.assign(movies,
movie(undefined, Actions.addMovie(movieObject)))
), {}));
}
};
Smell #2: Fat reducer + Object.assign everywhere
const movieCollection = (state = {
isLoading: false, sort: 'title', movies: {}
}, action) => {
switch(action.type) {
case ADD_MOVIECOLLECTION_WITH_MOVIES_LINE_BY_LINE:
return Object.assign({}, state, {
name: action.movieCollection.name,
movies: movies(undefined, {
type: 'ADD_MOVIES_LINE-BY-LINE',
movies: action.movieCollection.movies
})
});
case ADD_MOVIECOLLECTION_BY_FILE_START:
return Object.assign({}, state, {
name: action.movieCollection.name,
isLoading: true
});
}
};
This reducer alone 35 LOC!
(two more case statements)
Fix #1: Use reducer for every single attribute
const movieCollection = combineReducers({
isLoading,
sort,
movies,
name
});
Fix #1: No need for Object Assign. (before)
case ADD_MOVIECOLLECTION_BY_FILE_START:
return Object.assign({}, state, {
name: action.movieCollection.name,
isLoading: true
});
Fix #1: No need for Object Assign. (after)
case ADD_MOVIECOLLECTION_BY_FILE_START:
return action.movieCollection.name;
Fix #1: Makes it perfectly clear if attributes are not used, yet.
const sort = (state = 'title', action) => {
return state;
}
Fix #1: Makes it perfectly clear if attributes are not used, yet. (short)
const sort = (state = 'title', action) => state;
Fix #2: Create reducer from map
export default function createReducer(initialState, handlers) {
return (state = initialState, action) => {
handlers.hasOwnProperty(action.type)
? handlers[action.type](state, action)
: state;
}
}
Fix #2: Before
const isLoading = (state = false, action) => {
switch(action.type) {
case ADD_MOVIECOLLECTION_BY_FILE_START:
return true;
case UPDATE_MOVIECOLLECTION_BY_FILE:
return true;
case ADD_MOVIECOLLECTION_BY_FILE_FINISHED:
return false;
}
return state;
};
Fix #2: After
const isLoading = createReducer(INITIAL_STATE.isLoading, {
[ADD_MOVIECOLLECTION_BY_FILE_START]: () => true,
[UPDATE_MOVIECOLLECTION_BY_FILE]: () => true,
[ADD_MOVIECOLLECTION_BY_FILE_FINISHED]: () => false
});
- Slides: christophhaefner.de/events/busconf17/
- Reveal.js: Source code & documentation