Skip to content

Instantly share code, notes, and snippets.

@joemaffei
Last active September 20, 2019 16:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joemaffei/87d864d5602d00de2a5acc40642686b8 to your computer and use it in GitHub Desktop.
Save joemaffei/87d864d5602d00de2a5acc40642686b8 to your computer and use it in GitHub Desktop.
Refactoring React: reducer helper function
// Original
function clearTempStatuses(state) {
if (state == null) return [];
return state.map((quote) => {
const options = quote.options.map((option) => {
const { tempStatus: optionTempStatus, ...optionWithoutTempStatus } = option;
if (optionTempStatus) {
return { ...optionWithoutTempStatus, status: optionTempStatus };
}
return optionWithoutTempStatus;
});
const { tempStatus: quoteTempStatus, ...quoteWithoutTempStatus } = quote;
const newQuote = { ...quoteWithoutTempStatus, options: options };
if (quoteTempStatus) {
return { ...newQuote, status: quoteTempStatus };
}
return newQuote;
});
}
// 1. "state" can be confusing. This is manipulating data for the "quotes" reducer.
function clearTempStatuses(quotes) {
if (quotes == null) return [];
return quotes.map((quote) => {
const options = quote.options.map((option) => {
const { tempStatus: optionTempStatus, ...optionWithoutTempStatus } = option;
if (optionTempStatus) {
return { ...optionWithoutTempStatus, status: optionTempStatus };
}
return optionWithoutTempStatus;
});
const { tempStatus: quoteTempStatus, ...quoteWithoutTempStatus } = quote;
const newQuote = { ...quoteWithoutTempStatus, options: options };
if (quoteTempStatus) {
return { ...newQuote, status: quoteTempStatus };
}
return newQuote;
});
}
// 2. remove temporary options variable
function clearTempStatuses(quotes) {
if (quotes == null) return [];
return quotes.map((quote) => {
const { tempStatus: quoteTempStatus, ...quoteWithoutTempStatus } = quote;
const newQuote = { ...quoteWithoutTempStatus, options: quote.options.map((option) => {
const { tempStatus: optionTempStatus, ...optionWithoutTempStatus } = option;
if (optionTempStatus) {
return { ...optionWithoutTempStatus, status: optionTempStatus };
}
return optionWithoutTempStatus;
})};
if (quoteTempStatus) {
return { ...newQuote, status: quoteTempStatus };
}
return newQuote;
});
}
// 3. multiline returned objects for clarity
function clearTempStatuses(quotes) {
if (quotes == null) return [];
return quotes.map((quote) => {
const { tempStatus: quoteTempStatus, ...quoteWithoutTempStatus } = quote;
const newQuote = {
...quoteWithoutTempStatus,
options: quote.options.map((option) => {
const { tempStatus: optionTempStatus, ...optionWithoutTempStatus } = option;
if (optionTempStatus) {
return {
...optionWithoutTempStatus,
status: optionTempStatus,
};
}
return optionWithoutTempStatus;
})
};
if (quoteTempStatus) {
return { ...newQuote, status: quoteTempStatus };
}
return newQuote;
});
}
// 4. destructure object properties in function declarations
function clearTempStatuses(quotes) {
if (quotes == null) return [];
return quotes.map(({ tempStatus: quoteTempStatus, options, ...quoteWithoutTempStatus }) => {
const newQuote = {
...quoteWithoutTempStatus,
options: options.map(({ tempStatus: optionTempStatus, ...optionWithoutTempStatus }) => {
if (optionTempStatus) {
return {
...optionWithoutTempStatus,
status: optionTempStatus,
};
}
return optionWithoutTempStatus;
})
};
if (quoteTempStatus) {
return { ...newQuote, status: quoteTempStatus };
}
return newQuote;
});
}
// 5. move condition in options.map callback to the returned object (which requires destructuring `status`)
function clearTempStatuses(quotes) {
if (quotes == null) return [];
return quotes.map(({ tempStatus: quoteTempStatus, options, ...quoteWithoutTempStatus }) => {
const newQuote = {
...quoteWithoutTempStatus,
options: options.map(({ tempStatus: optionTempStatus, status: optionStatus, ...optionWithoutTempStatus }) => {
return {
...optionWithoutTempStatus,
status: optionTempStatus || optionStatus,
};
})
};
if (quoteTempStatus) {
return { ...newQuote, status: quoteTempStatus };
}
return newQuote;
});
}
// 6. do the same thing for the quotes.map callback
function clearTempStatuses(quotes) {
if (quotes == null) return [];
return quotes.map(({ tempStatus: quoteTempStatus, options, status: quoteStatus, ...quoteWithoutTempStatus }) => {
const newQuote = {
...quoteWithoutTempStatus,
options: options.map(({ tempStatus: optionTempStatus, status: optionStatus, ...optionWithoutTempStatus }) => {
return {
...optionWithoutTempStatus,
status: optionTempStatus || optionStatus,
};
})
};
return {
...newQuote,
status: quoteTempStatus || quoteStatus,
};
});
}
// 7. remove temporary newQuote variable
function clearTempStatuses(quotes) {
if (quotes == null) return [];
return quotes.map(({ tempStatus: quoteTempStatus, options, status: quoteStatus, ...quoteWithoutTempStatus }) => {
return {
...quoteWithoutTempStatus,
options: options.map(({ tempStatus: optionTempStatus, status: optionStatus, ...optionWithoutTempStatus }) => {
return {
...optionWithoutTempStatus,
status: optionTempStatus || optionStatus,
};
}),
status: quoteTempStatus || quoteStatus,
};
});
}
// 8. extract callbacks into function declarations
function clearTempStatuses(quotes) {
if (quotes == null) return [];
function quotesMapCallback({
tempStatus: quoteTempStatus,
options,
status: quoteStatus,
...quoteWithoutTempStatus
}) {
return {
...quoteWithoutTempStatus,
options: options.map(optionsMapCallback),
status: quoteTempStatus || quoteStatus,
};
}
function optionsMapCallback({
tempStatus: optionTempStatus,
status: optionStatus,
...optionWithoutTempStatus
}) {
return {
...optionWithoutTempStatus,
status: optionTempStatus || optionStatus,
};
}
return quotes.map(quotesMapCallback);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment