React is a JavaScript library, so better JavaScript usually means better React. You do not need advanced tricks to write good components. Most improvements come from small habits: clear names, predictable state updates, safe conditions, and simple data transformations.
This lesson collects ten practical tips you can apply while building React components. Each tip focuses on code that stays readable after your app grows beyond a few files.
Short names are fine for tiny loops, but React components often mix props, state, handlers, and derived values. Clear names help you understand the component without rereading every line.
const activeUsers = users.filter(user => user.isActive);
const hasActiveUsers = activeUsers.length > 0;
Avoid names like data, item, or value when a more specific word is obvious. A component that says selectedCourse, completedLessons, or isSavingProfile explains itself.
React state should be treated as read-only. Instead of changing an array or object directly, create a new one. This makes updates predictable and helps React detect that the UI should re-render.
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, completed: true } : todo
));
Avoid code like todos.push(newTodo) or user.name = "Asha" when those values are stored in state. Create a new array or object with the updated values.
React makes it easy to render different UI based on a condition, but deeply nested ternary expressions become hard to scan.
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Something went wrong.</p>;
return <CourseList courses={courses} />;
Early returns are often easier to read than one large return block with many conditions inside it.
If a value can be calculated from props or state, compute it before the JSX. This keeps the markup focused on structure.
const completedCount = lessons.filter(lesson => lesson.completed).length;
const progressText = `${completedCount} of ${lessons.length} lessons complete`;
return <p>{progressText}</p>;
This pattern also makes debugging easier because you can inspect the derived values separately.
React list rendering pairs naturally with JavaScript array methods such as map, filter, and sort.
const visibleLessons = lessons.filter(lesson => lesson.published);
return (
<ul>
{visibleLessons.map(lesson => (
<li key={lesson.id}>{lesson.title}</li>
))}
</ul>
);
Always provide a stable key when rendering lists. Prefer an id from your data instead of the array index when the list can be reordered, filtered, or edited.
Small expressions inside JSX are fine. Large calculations, chained filters, or nested conditions can make the render output noisy.
const topCourses = courses
.filter(course => course.rating >= 4.5)
.slice(0, 3);
Then render topCourses in the JSX. The component becomes easier to read because the data preparation and the UI output are separate.
Data from APIs can be incomplete while loading. Optional chaining helps avoid errors when a nested value is not ready yet.
return <h2>{profile?.name || "Guest"}</h2>;
Use it for uncertain data, but do not hide real bugs with too many fallback values. If a field is required, validate it where the data enters your app.
An event handler should usually describe one user action. If it starts doing many unrelated things, move some logic into helper functions.
function handleSave() {
const nextProfile = buildProfileFormData(formValues);
saveProfile(nextProfile);
}
Focused handlers are easier to test and reuse. They also make button clicks, form submits, and input changes easier to trace.
const by DefaultUse const for values that are not reassigned. This makes your intent clear and prevents accidental changes.
const lessonTitle = "React State";
const isCompleted = completedLessons.includes(lessonTitle);
Use let only when a variable truly needs to change. In React components, most values are derived once per render, so const is usually the right choice.
When the same JavaScript logic appears in several components, move it into a helper function or a custom hook.
function formatLessonCount(count) {
return count === 1 ? "1 lesson" : `${count} lessons`;
}
For logic that uses React state or effects, a custom hook is often better. For plain formatting or calculations, a simple function is enough.
Open one of your React components and look for three things:
Refactor only one part at a time, then run the component and confirm the UI still behaves the same.
Good React code depends on good JavaScript habits. Use clear names, keep state immutable, derive values before JSX, render lists with stable keys, and extract repeated logic when it starts to distract from the component's purpose. These small choices make components easier for both beginners and experienced developers to understand.