How I Used ChatGPT for Rapid Onboarding and Development
With the advent of ChatGPT, there has been concerns on it soon replacing a lot of jobs. Even companies scrambled to device policies restricting use of ChatGPT for work on data leak concerns. But if used well, it can be a force multiplier, particularly in the field of software development. In this article, I wanted to share how I could leverage ChatGPT to quickly scale the learning curve and to be a better developer, all the while adhering to all possible restrictions on its use.
When I was moved into a new team, I was asked if I could look into some UI issues as the new Amazon Developer Portal UI was due for dial-up and there were several high severity issues to fix. I didn’t have a proper work experience with any modern UI frameworks, although I could call myself proficient in Javascript. The project was using React and the components were coded in Typescript, both of which I had no clue. Our front-end engineer was away for sometime, there was very little help I could get from the team.
Asking pointed questions on programming
For fixing the relatively “simple” issues, I could prompt ChatGPT with pointed questions. As a real example,
“I’m using promise.all to perform an action when all files are uploaded. However if one of the upload failed, the error function is called. How can I change it in such a way that any errors can be handled later and proceed with the function in the rest?”
ChatGPT’s response to this was highly accurate and relevant and did solve the problem for me.
If you want to use
Promise.all
to perform an action when all files are uploaded but ignore any errors that may occur during the upload process, you can handle the errors within thePromise.all
callback and continue with the processing of successful uploads. You can achieve this by usingPromise.all
along withPromise.allSettled
. Here’s an example:
const uploads = [uploadFile1(), uploadFile2(), uploadFile3()];
Promise.allSettled(uploads)
.then(results => {
const successfulResults = results.filter(result => result.status === 'fulfilled');
const successfulUploads = successfulResults.map(result => result.value);
// Process successful uploads here
console.log('Successful Uploads:', successfulUploads);
})
.catch(error => {
// Handle any errors that occurred during uploading
console.error('Error during uploads:', error);
});
I didn’t even know something like Promise.allSettled
existed. Such responses helped me a lot to get the solution first and then understand the scenario. Such pointed questions helped me burn down the issues backlog quite quickly without much of an expertise.
Prompting on specific behaviour
Once the few “very simple” issues were fixed, the rest of the issues demanded in-depth knowledge in React. Waiting to learn and then start the fixes was not an option. That is where I could use ChatGPT to the best. I started with the behaviour- asked it what could be the reason for so and so behaviour, sharing example code from the very little I could comprehend from the actual code (prompting with the actual code was prohibited by policy and would not help a lot perhaps due to the interconnected components).
For instance, there was a long pending issue where the screen was going blank on some action. While looking at the browser logs, I could see something worth pondering. This was my query:
I am getting the following error in React when using a hook within a method. How can I possibly fix this? Uncaught Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement in React Hooks
It responded with a detailed explanation along with a few examples.
The error message you’re encountering typically occurs when you use React Hooks (like useState, useEffect, useContext, etc.) inside a function or method and there’s a conditional early return statement that prevents some hooks from being called in certain cases.
React Hooks must be called unconditionally at the top level of your functional component or custom hook. They should not be placed inside nested functions or conditional blocks. To fix this error, follow these steps:
Ensure that you’re using hooks directly in the functional component or custom hook, not inside nested functions or conditional blocks.
Incorrect:
function MyComponent() {
if (someCondition) {
useState(0); // Incorrect - inside a conditional block
}
return (
// JSX
);
}
Correct:
function MyComponent() {
const [value, setValue] = useState(0); // Correct - at the top level
if (someCondition) {
// ...
}
return (
// JSX
);
}
Make sure that you’re not using hooks inside loops, conditions, or other functions that might not always execute. Hooks should be called in the same order on every render.
If you have conditional logic that determines whether a hook should be used, you can use the
useState
,useEffect
, or other hooks conditionally within the component’s top-level scope. Just make sure that all paths through your component include the same hooks.Here’s an example of using
useEffect
conditionally:
function MyComponent(props) {
useEffect(() => {
if (props.someCondition) {
// Perform some side effect when someCondition is true
}
}, [props.someCondition]);
return (
// JSX
);
}
By following these guidelines, you should be able to resolve the “Rendered fewer hooks than expected” error in your React component.
I skimmed the code looking for such patterns and found a place where a similar usage was there. Made the modifications as per the suggestions to fix the error, all under an hour. In similar fashion, I also could fix a scenario where the data was not getting refetched when using react-query, although the query was in-fact getting invalidated- but this time prompted based on the sequence of events instead of logs.
Follow-up questions
This is another aspect that was unique with ChatGPT. Attempting certain recommendations given might not always work due to the intricate nature of projects. What helped the most is the ability to ask follow-up questions. For instance, here is one real conversation I had.
In react-queries, how can I invalidate all queries starting with a path?
Aswin
In React Query, you can invalidate all queries starting with a certain path by using the
queryCache
object’sinvalidateQueries
method with a predicate function. You can define a predicate function that checks if a query key starts with the specified path, and then invalidate all matching queries.Here’s an example of how you can do this:
import { useQueryClient } from 'react-query';
function MyComponent() {
const queryClient = useQueryClient(); // Function to invalidate queries starting with a certain path
const invalidateQueriesStartingWith = (path) => {
queryClient.invalidateQueries((queryKey) => {
// Check if the query key starts with the specified path
return queryKey.startsWith(path);
});
}; // Example usage to invalidate queries starting with "/users"
const handleInvalidateUsersQueries = () => {
invalidateQueriesStartingWith('/users');
};
return (
<div>
<button onClick={handleInvalidateUsersQueries}>
Invalidate /users Queries
</button>
{/* Your component content */}
</div>
);
}
In this example,
invalidateQueriesStartingWith
is a function that takes a path as an argument and usesqueryClient.invalidateQueries
with a predicate function to invalidate all queries that start with the specified path. You can call this function when needed to invalidate the relevant queries.Remember to adjust the path and the predicate function according to your specific use case and query key structure.
ChatGPT
Now while following the recommendations, I got some weird error which I could not immediately comprehend. So I asked a follow-up question and ChatGPT responded generously.
While using this code, I am getting this error: Value of type (queryKey: any) => any has no properties in common with type InvalidateQueryFilters<unknown> . Did you mean to call it?
Aswin
I apologize for the confusion. The error you’re encountering is because TypeScript is inferring the wrong type for the predicate function. To resolve this issue, you can explicitly specify the type for the predicate function. Here’s an updated version of the code that includes TypeScript type annotations:
import { useQueryClient } from 'react-query';
function MyComponent() {
const queryClient = useQueryClient(); // Function to invalidate queries starting with a certain path
const invalidateQueriesStartingWith = (path: string) => {
queryClient.invalidateQueries((queryKey: unknown) => {
// Check if the query key starts with the specified path
return typeof queryKey === 'string' && queryKey.startsWith(path);
});
}; // Example usage to invalidate queries starting with "/users"
const handleInvalidateUsersQueries = () => {
invalidateQueriesStartingWith('/users');
};
return (
<div>
<button onClick={handleInvalidateUsersQueries}>
Invalidate /users Queries
</button>
{/* Your component content */}
</div>
);
}
In this updated code, I’ve specified the types for the
path
parameter as a string and thequeryKey
parameter asunknown
. Additionally, I’ve added a type check to ensure that thequeryKey
is a string before checking if it starts with the specified path. This should resolve the TypeScript error.ChatGPT
This time the solution did work. This scenario would have been really difficult to navigate with traditional search. In such scenarios, ChatGPT could be compared to a human companion while pair programming.
The catch
Although it seems like a perfect one-that-fit-all solution, that is not usually the case. As common with LLMs, the responses are not always accurate. So one should know what they are doing and watch out for edge cases and other risks when using as an aid for software development. Here are a few things I do:
- Trust, but verify- Always verify the solutions proposed. Looking up the docs for any unknown APIs or methods suggested would help a lot. Similarly when using complex logics, do a deep code walkthrough.
- Do not copy-paste- This might seem ironic, but I would strongly advise against copy-pasting code as is. Copyright and ethical boundaries around LLM responses are strongly debated. In any case, it is always better to read, understand and then implement as that would help us be a better developer as well.