ChatGPT is hot right now, so I thought I should experiment with letting it write a blog post. It did surprisingly well. The following is more than half AI-generated. For the most part, the first paragraph in each section is ChatGPT, and the more in-depth explanation and code examples are from me for added clarity. I also reordered the sections to flow better. Enjoy!
When it comes to writing React code, it's important to prioritize readability. Readable code is easier to understand and maintain, which can save your team time and effort in the long run. Let’s go over some tips for writing React code that’s easy to read and understand.
Use Descriptive Names for Components, Props, and State Variables
One of the most important aspects of readable React code is using descriptive names for your components. Choose names that accurately describe what the component does or what it represents. Descriptive names can make it easier for other developers to understand your code and for you to find and reference specific components later on.
export function Count({ count }) {
return <div className="count">{count}</div>;
}
What does that component do ? Let’s try again with descriptive naming:
export function PagesReadDisplay({ pagesReadCount }) {
return <div className="pagesRead">{pagesReadCount}</div>;
}
Your build is going to minify and compress that code. Long and descriptive names won’t cost you anything more than a few extra keystrokes, which your editor is going to autocomplete for you anyway.
Write Clear and Concise Code
Clear and concise code is easier to read and understand than code that's verbose or confusing. When writing React code, strive for clarity and simplicity. Avoid “smart” code or complicated logic that can make it difficult to understand the code’s intention.
type ApiTodo = {
userId: number;
id: number;
title?: string;
completed?: boolean;
};
type Todo = {
userId: string;
id: string;
title: string;
completed: boolean;
};
type JSONResponse = {
data?: Array<ApiTodo>;
errors?: Array<{ message: string }>;
};
export async function fetchData(): Promise<Todo[]> {
const response = await fetch(
"https://jsonplaceholder.typicode.com/todos"
);
const { data: apiTodos, errors }: JSONResponse = await response.json();
if (response.ok && apiTodos) {
return apiTodos
.map((todo: ApiTodo) => ({
userId: todo.userId.toString(),
id: todo.id.toString(),
title: todo.title || "",
completed: todo.completed === true ? true : false,
}))
.sort((a, b) => a.title.localeCompare(b.title))
.sort((a, b) => {
if (a.completed && !b.completed) {
return 1;
} else if (!a.completed && b.completed) {
return -1;
} else {
return 0;
}
});
} else {
throw new Error(errors?.[0].message || "Something went wrong");
}
}
Eww. How about we break that up?
type ApiTodo = {
userId: number;
id: number;
title?: string;
completed?: boolean;
};
type Todo = {
userId: string;
id: string;
title: string;
completed: boolean;
};
type JSONResponse = {
data?: Array<ApiTodo>;
errors?: Array<{ message: string }>;
};
export async function fetchTodos(): Promise<Todo[]> {
const response = await fetch(
"https://jsonplaceholder.typicode.com/todos"
);
const { data: apiTodos, errors }: JSONResponse = await response.json();
if (response.ok && apiTodos) {
const todos = apiTodos.map(transformApiTodo);
return sortTodosByIncomplete(sortTodosByAlphabetical(todos));
} else {
throw new Error(errors?.[0].message || "Something went wrong");
}
}
// The following can move to a 'utils' directory and can be reused elsewhere
function transformApiTodo(apiTodo: ApiTodo): Todo {
return {
userId: apiTodo.userId.toString(),
id: apiTodo.id.toString(),
title: apiTodo.title || "",
completed: apiTodo.completed === true ? true : false,
};
}
function sortTodosByAlphabetical(todos: Todo[]): Todo[] {
return todos.sort((a, b) => a.title.localeCompare(b.title));
}
function sortTodosByIncomplete(todos: Todo[]): Todo[] {
return todos.sort((a, b) => {
if (a.completed && !b.completed) {
return 1;
} else if (!a.completed && b.completed) {
return -1;
} else {
return 0;
}
});
}
We went from 48 lines to 58, but now we have specific and well-named functions, which is a trade-off I’m happy to make. These new functions are now reusable and make it easier to read the parent fetchTodos
. When you find your code getting hard to follow, it might be because your function is handling too many things.
Keep Components Small and Focused
Another important aspect of readable React code is keeping your components small and focused. Components are just functions in a different form, and the Single Responsibility Principle applies to both.
Rather than creating large, complex components that try to do too much, break them down into smaller, more specific components. This can make it easier to understand how each component fits into the overall structure of your application.
While it can be hard to define what exactly makes a component small and focused, I have a few guidelines I use:
-
Is the component file longer than 100 lines? 200 lines?
-
Is the component tracking more than 3 state values?
-
Does the component need multiple useEffects?
These rules are a signal that I should consider breaking my component up into multiple components and/or hooks. While these rules do not mean that I have to break up my component, they do correlate with higher levels of complexity which makes a component harder to change in the future.
Format Your Code Consistently
Consistent formatting can also contribute to the readability of your React code. Use consistent indentation, spacing, and line breaks throughout your code. Consider using a code formatter tool to help ensure that your code is formatted consistently across your entire application.
We like Prettier. It integrates with most major code editors, has a strong set of defaults, and can be set up to run automatically every time you save. When you start using Prettier, code quality improves, and the team stops wasting time on debates about formatting.
Comment Your Code
Finally, commenting your code can be an effective way to improve its readability. Use comments to explain what your code is doing, why you made certain decisions, and any potential pitfalls or edge cases that you encountered. Comments can be especially helpful for other developers who may need to work with your code in the future.
If you followed the other tips to use descriptive naming and kept your components small, it should be fairly easy to understand your code without comments, but a few comments in important places can make a big difference.
-
Breaking best practices, like when ignoring exhaustive dependencies on a useEffect hook.
-
Documenting performance optimizations. High-performing code can be hard to understand.
-
Linking documentation for a library
Conclusion
In summary, writing readable React code is an important aspect of building maintainable, scalable applications. By using descriptive names for your components, keeping your components small and focused, using props and state effectively, writing clear and concise code, formatting your code consistently, and commenting your code, you can write React code that's easy to understand and maintain. By prioritizing readability in your code, you can save time and effort in the long run and make your development process more efficient.
Meta Conclusion, How Did ChatGPT Do?
I’m impressed. I did remove one section that was basically a repeat, but otherwise, the tips are valid. My main complaint is the tips weren’t detailed enough.
Is the “AI” just a glorified search engine pulling chunks of existing articles on the web?
I ran the article through Grammarly’s online plagiarism detector, and nothing was flagged. While the model is certainly training on other web content, it’s combining those sources in a unique way, maybe not all that differently from how so many content farms do it.
If you don’t know what I mean by content farm, there are businesses that employ writers to research and produce blog posts at high volume. These articles tend to be fairly superficial and contain parts that don’t quite make complete sense, as if the author doesn’t really understand the topic. What I get from ChatGPT reads a similar way, and maybe that’s because it's trained on web content from these content farms.
Will I use ChatGPT in the future for blog posts?
Yes. I found the content I got from ChatGPT to be an excellent starting point. I reordered and then added depth, but it definitely saved me time getting started.
Is AI going to replace me as a developer?
I also have used GitHub Copilot, a code-assist AI, and I find that both AIs are tools to enhance my own abilities. Neither can create anything useful without me. One day, AI might take my job, but today is not that day.
Avoiding AI helpers is a bit like writing a book with a typewriter. Technology presses on whether we like it or not, it's up to you to decide if you want to be left behind.
What are your thoughts?
We’d love to hear them! Join the Bitovi Community Discord to chat about React, AI, or anything you’re working on. 🥚