Imagine having a pairing buddy to help you with those finicky Pull Request (PR) reviews. During reviews, when it comes to refining small code snippets, Large Language Models (LLM) using Artificial Intelligence (AI) is my new friend and pairing buddy. Using AI, developers can quickly offer improvement suggestions based on identified optimisation opportunities. In this blog post, I’d like to share a few examples from my recent PR reviews, where AI not only pinpointed precise code improvements but also provided insightful explanations on how these changes improve the readability and performance of the code. When I say “AI” in this post, I’m referring to text generating models like ChatGPT, Claude AI, or DeepSeek.
It is essential to understand that AI does not review the PRs. Instead, it is used as a tool whose primary function is to assist me with the reviews including:
- Informative comments: AI helps to write thoughtful, contextual comments that facilitate constructive dialogue about the code.
- Code improvements suggestions: Alongside review comments, AI suggests code changes that could enhance the overall quality.
Let’s dive into the examples straight away.
Example 1: Optimising using Map
data structure
In this example, the suspicion was an “m x n” array traversal on
category.products
which was inefficient. I suggested an optimisation by
avoiding the “m x n” traversal using a hash map for faster lookups. AI confirmed
the approach and also provided back the refactored code as output.
Code changes before and after refactor
export const getSelectedServerTagAssignments = (
tagAssignments: SelectedTagAssignments[],
defaultTagAssignments: TagSectionType[],
) => {
- const tagAssignmentsArray = tagAssignments.map((assignment) => ({
- id: assignment.productId,
- quantity: assignment.quantity,
- }))
+ const tagAssignmentsMap = new Map(
+ tagAssignments.map((assignment) => [assignment.productId, assignment]),
+ )
return defaultTagAssignments.map((category) => ({
...category,
products: category.products.map((product) => {
- const matchingAssignment = tagAssignmentsArray.find(
- (assignment) => assignment.id === product.id,
- )
+ const matchingAssignment = tagAssignmentsMap.get(product.id)
const baseProduct = {
...product,
quantity: matchingAssignment ? matchingAssignment.quantity : 0,
}
if (!category.allowDuplicateSelections) {
return {
...baseProduct,
isSelected: !!matchingAssignment,
}
}
return baseProduct
}),
}))
}
Prompt to AI
// Code snippet before refactor
Are the array iterations in this function implemented optimally? Can we reduce any iterations and determine the return value in a better way? Also any other ways to improve the readability of this function?
PR Review comment
Disclaimer: This comment was inspired by AI based on a hunch that the nested iteration could be avoided.
This is what happens in the current version of the function:
- Multiple Iterations: The function creates a tagAssignmentsArray by mapping over tagAssignments, and then it iterates over defaultTagAssignments with a nested iteration over category.products. This results in multiple iterations.
- Redundant Property Mapping: Some properties are being mapped and re-mapped unnecessarily.
- Readability: The nested structure can be hard to read and understand. I think we can rewrite this function to use a Map data structure
tagAssignmentsMap
instead oftagAssignmentsArray
which is performant.// Code snippet after refactor
I did not know
Map
data structure existed in JS/TS and was a learning for me. All the tests pass after the above change. What do you think?
Example 2: Simplify for readability
When reviewing this example, it was clear at first glance that the new
conditional check had introduced a redundant dispatch
call, and the code could
benefit from some clean-up. While drafting a comment to point this out would
have been straightforward, AI stepped in and instantly provided the elegant
refactored code. It was a small but satisfying win for efficiency.
Code changes before and after refactor
useEffect(() => {
if (doesItemTagWithSections) {
+ let sections = product?.sections
if (serverItemDetail && serverItemId) {
+ sections = getSelectedServerTagAssignments(
- const newTagAssignments = getSelectedServerTagAssignments(
serverItemDetail.tagAssignments,
tagSections,
)
- dispatch(
- copyTagSectionsAsync({
- lineId: tagLineItem,
- sections: newTagAssignments,
- }),
- )
- } else {
- dispatch(
- copyTagSectionsAsync({
- lineId: tagLineItem,
- sections: product?.sections,
- }),
- )
}
+ dispatch(
+ copyTagSectionsAsync({
+ lineId: tagLineItem,
+ sections,
+ }),
+ )
}
}, [product?.sections])
Prompt to AI
// Code snippet before refactor
Can we refactor this such that we call
dispatch
only once?
PR Review comment
// Code snippet after refactor
Does this simplify the code? In this
effect
, instead of calling thedispatch
twice, we get the arguments conditionally and then calldispatch
once.
Example 3: Unique keys instead of index
Passing the array index
as a key to a React component is a common developer
mistake. While it might seem convenient, it can lead to subtle bugs. AI helped
me articulate this clearly as a PR review comment.
Code changes before refactor
<FlatList
data={currentData}
keyExtractor={(item, index) => `${item.favoriteName}-${index}`}
...
/>
Prompt to AI
// Code snippet above
Explain why it’s not a good idea to use index as keys in keyExtractor
in 50
words or less.
PR Review comment
Would it be good to have an
id
in the fake data and use that as a key here? If the list is reordered, filtered, or items are added/removed, the index of each item will change. This can cause React to mistakenly think that the same item is a different one, leading to unnecessary re-renders or incorrect behaviour. It’s generally not a good idea to useindex
for key and alsoname
is not guaranteed to be unique.
Example 4: Simplify for readability
The code in this example felt verbose and hard to understand at first glance. These are the instances where you don’t need to involve AI even though it’s handy. Did I ask AI or not? :)
Code changes before refactor
const hasTagAssignments = (orderItem: OrderLineType): boolean =>
(orderItem.tagAssignments.length ?? 0) > 0
PR Review comment
const hasTagAssignments = (orderItem: OrderLineType): boolean => orderItem.tagAssignments?.length > 0
Does this condition achieve the outcome you hope and more readable?
Conclusion
In the past, my PR reviews and feedback might have been less detailed with only suggestions making the developer guess the implementation details or pair program with me to implement the same. But with AI, I’ve started to provide detailed feedback with code suggestions that can be pasted immediately reducing friction. As a result, I’ve received a lot of positive feedback from developers recently making my review efforts worthwhile and rewarding.
Finally, it’s essential to rely on intuition and use AI as a tool to assist in the review process. If AI played a significant role in crafting a specific comment, please disclose this by including a disclaimer. The final review comment should focus on selecting the most useful insights from the AI’s responses and presenting them in a natural, human-like manner, rather than copying the entire output returned.
Throughout this blog post, I’ve been referencing AI, and you may be wondering if it’s ChatGPT. Despite ChatGPT’s popularity, I’ve been using different LLMs for my code reviews. I’ll write more about this and share my development workflow in a future post. Stay tuned!