Skip to main content

Best Practices and Anti-Patterns

Level: Beginner

ℹ️ What You'll Learn
  • Component naming and file organization
  • Folder structure for scalability
  • Avoiding inline functions and object recreation
  • Proper key usage in lists
  • State placement and lifting
  • Prop drilling alternatives
  • Performance optimization patterns
  • Code review checklist for SMS

Why This Matters

Best Practices and Anti-Patterns is part of building maintainable React applications. You will use it when creating student dashboards, forms, tables, API-connected screens, routing flows, and reusable UI components.

Learn to write React code that's maintainable, performant, and bug-free.

The Problem

Beginners often write React code that works for a small demo but becomes difficult when data, forms, API calls, and reusable components grow. This lesson explains Best Practices and Anti-Patterns in a way that helps you build predictable UI for real .NET Web API projects.

Component Design

✓ Keep Components Small

// ❌ Too large — 300 lines in one component
function StudentDashboard() {
// Student list, marks, attendance, fees, actions all here
}

// ✓ Better — split into smaller pieces
function StudentDashboard() {
return (
<>
<StudentInfo />
<StudentMarks />
<StudentAttendance />
<StudentFees />
</>
);
}

✓ Props Over Drilling

// ❌ Prop drilling
<SchoolContext>
<ClassList students={students} />
</SchoolContext>

// ✓ Use Context
<SchoolProvider>
<ClassList />
</SchoolProvider>

✓ Default Props

// ❌ Manual defaults in function
function StudentCard({ student }) {
const name = student?.name || 'Unknown';
return <h3>{name}</h3>;
}

// ✓ Default parameters
function StudentCard({ student = {} }) {
return <h3>{student.name || 'Unknown'}</h3>;
}

Performance

✓ Memoize Components

// ❌ Re-renders even if props unchanged
function StudentCard({ student }) {
return <div>{student.name}</div>;
}

// ✓ Memoized — only re-renders if props change
const StudentCard = React.memo(function StudentCard({ student }) {
return <div>{student.name}</div>;
});

✓ Key in Lists

// ❌ Index as key (breaks if list reorders)
{students.map((s, index) => (
<li key={index}>{s.name}</li>
))}

// ✓ Unique ID as key
{students.map(s => (
<li key={s.id}>{s.name}</li>
))}

✓ Lazy Load Components

const StudentDetail = React.lazy(() => import('./StudentDetail'));

function App() {
return (
<Routes>
<Route
path="/students/:id"
element={
<Suspense fallback={<Loading />}>
<StudentDetail />
</Suspense>
}
/>
</Routes>
);
}

Code Organization

✓ Separate Concerns

// ❌ API logic in component
function StudentList() {
const [students, setStudents] = useState([]);

useEffect(() => {
fetch('/api/students')
.then(r => r.json())
.then(data => setStudents(data));
}, []);

return students.map(s => <StudentCard key={s.id} student={s} />);
}

// ✓ Extract API logic
import { useFetchStudents } from './hooks';

function StudentList() {
const students = useFetchStudents();
return students.map(s => <StudentCard key={s.id} student={s} />);
}

✓ Custom Hooks for Logic

// ❌ Complex state in component
function StudentForm() {
const [form, setForm] = useState({});
const [errors, setErrors] = useState({});

const handleChange = () => { /* ... */ };
const handleSubmit = () => { /* ... */ };
const validate = () => { /* ... */ };

return <form onSubmit={handleSubmit}>{/* ... */}</form>;
}

// ✓ Extract to custom hook
function useStudentForm() {
const [form, setForm] = useState({});
const [errors, setErrors] = useState({});
const handleChange = () => { /* ... */ };
const handleSubmit = () => { /* ... */ };
return { form, errors, handleChange, handleSubmit };
}

function StudentForm() {
const { form, handleChange, handleSubmit } = useStudentForm();
return <form onSubmit={handleSubmit}>{/* ... */}</form>;
}

Error Handling

✓ Always Handle Loading/Error States

// ❌ No loading state
function StudentList() {
const [students, setStudents] = useState([]);

useEffect(() => {
fetch('/api/students').then(r => r.json()).then(setStudents);
}, []);

return students.map(s => <StudentCard key={s.id} student={s} />);
}

// ✓ Handle all states
function StudentList() {
const [students, setStudents] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
fetch('/api/students')
.then(r => r.json())
.then(data => { setStudents(data); setLoading(false); })
.catch(err => { setError(err); setLoading(false); });
}, []);

if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;

return students.map(s => <StudentCard key={s.id} student={s} />);
}

State Management

✓ Local State by Default

// ❌ Global state for everything
const [searchQuery, setSearchQuery] = useContext(GlobalState);

// ✓ Local state for temporary data
function StudentSearch() {
const [searchQuery, setSearchQuery] = useState('');
return <input value={searchQuery} onChange={e => setSearchQuery(e.target.value)} />;
}

✓ useReducer for Complex Logic

// ❌ Multiple useState for related data
function StudentManager() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [className, setClassName] = useState('');
}

// ✓ useReducer
function StudentManager() {
const [form, dispatch] = useReducer(formReducer, initialState);
}

Naming Conventions

✓ Clear, Semantic Names

// ❌ Unclear
function D({ d }) {
return <div onClick={() => f(d.id)}>{d.n}</div>;
}

// ✓ Clear
function StudentCard({ student }) {
return <div onClick={() => handleDelete(student.id)}>{student.name}</div>;
}

✓ Function Naming

// ❌ Unclear
const h = () => { /* ... */ };

// ✓ Clear
const handleStudentDelete = () => { /* ... */ };
const validateForm = () => { /* ... */ };
const fetchStudents = () => { /* ... */ };

Testing

✓ Write Testable Components

// ❌ Hard to test — API call inside
function StudentList() {
useEffect(() => {
fetch('/api/students').then(/* ... */);
}, []);
}

// ✓ Easy to test — pass data via props
function StudentList({ students = [] }) {
return students.map(s => <StudentCard key={s.id} student={s} />);
}

Security

✓ Sanitize User Input

// ❌ XSS vulnerability
const comment = '<img src=x onerror=alert("XSS")>';
<div>{comment}</div>

// ✓ React escapes by default
<div>{userInput}</div>

// For HTML content, use DOMPurify
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(html) }} />

✓ Never Expose Secrets

// ❌ Secrets in frontend code
const API_KEY = 'sk-secret-key-12345';

// ✓ Keep secrets on backend
const response = await fetch('/api/protected-endpoint');

Common Anti-Patterns

❌ Mutating Props

// ❌ Wrong
function StudentCard({ student }) {
student.name = "Changed";
return <div>{student.name}</div>;
}

❌ Direct DOM Manipulation

// ❌ Wrong
function StudentList() {
useEffect(() => {
document.getElementById('list').innerHTML = '<li>Student 1</li>';
}, []);

return <ul id="list"></ul>;
}

// ✓ Use React state
function StudentList() {
return (
<ul>
{students.map(s => <li key={s.id}>{s.name}</li>)}
</ul>
);
}

❌ Async in useEffect without Cleanup

// ❌ Wrong — missing cleanup
useEffect(() => {
const interval = setInterval(() => {
// ...
}, 1000);
}, []);

// ✓ Correct
useEffect(() => {
const interval = setInterval(() => {
// ...
}, 1000);

return () => clearInterval(interval);
}, []);

File Structure

src/
├── components/
│ ├── StudentCard.jsx
│ ├── StudentList.jsx
│ ├── StudentForm.jsx
├── pages/
│ ├── StudentListPage.jsx
│ ├── StudentDetailPage.jsx
├── hooks/
│ ├── useFetch.js
│ ├── useForm.js
├── services/
│ ├── studentService.js
│ ├── teacherService.js
├── contexts/
│ ├── AuthContext.js
│ ├── SchoolContext.js
├── App.jsx
├── index.jsx

Key Takeaways

  • Small, focused components
  • Handle loading and errors
  • Use custom hooks for logic
  • Memoize when needed
  • Keep state local
  • Clear naming
  • Secure code
  • Testable design
⚠️ Never Do This
  1. Mutate props or state directly
  2. Call hooks conditionally
  3. Expose API keys in frontend
  4. Skip error handling
  5. Create giant components
  6. Use array index as key in lists
💡 Code Review Checklist

Before committing:

  • Components are small and focused
  • Error states handled
  • Loading states shown
  • No prop drilling (< 2 levels)
  • Performance optimized
  • Accessible (semantic HTML)
  • Consistent naming
🤖Use AI to Learn Faster

Use ChatGPT, Claude, or Copilot to go deeper on React Best Practices. Try these prompts:

  • "What's the difference between good and bad component design?"
  • "When should you use memo() vs. useCallback()?"
  • "What's an anti-pattern you should avoid?"
  • "Quiz me on React best practices"

💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.

Quick Definitions

  • Best Practices and Anti-Patterns - The main React concept explained in this lesson.
  • Component - A reusable function that returns UI.
  • Props/state/effects - Core React ideas used to pass data, remember data, and run side effects.
  • Real project usage - How this appears in forms, dashboards, routes, and API-connected pages.

Common Mistakes

  • Copying React code without understanding data flow
  • Mutating arrays or objects directly instead of creating new values
  • Forgetting keys, dependencies, loading states, or error states where needed
  • Putting too much logic in one component
  • Not testing the screen with realistic School Management System data

Practice Task

Create a small React example using Best Practices and Anti-Patterns. Keep it focused on one School Management System screen.

Suggested practice:

  1. Build a small component or page for students, attendance, marks, or fees.
  2. Pass realistic data into the component.
  3. Add one success state and one empty/error state where relevant.
  4. Explain the data flow in your own words.
  5. Rebuild the same example once without looking at the article.

Quick Revision

QuestionAnswer
What is the main idea?Understand and apply Best Practices and Anti-Patterns in React.
Where is it used?Student dashboards, forms, tables, routes, and API-connected screens.
What should beginners focus on?Clear components, predictable data flow, and small examples.
What is the best debugging habit?Check props, state, render output, and browser console step by step.
🎯 How would you explain Best Practices and Anti-Patterns in an interview?

Best Practices and Anti-Patterns is a React concept used to build clear, reusable, and predictable user interfaces. I would explain the problem it solves, show a small component example, and mention a common mistake beginners should avoid.

🎯 Where is this used in a real React project?

It is used in screens like student lists, admission forms, attendance dashboards, marks reports, routing pages, and API-connected admin panels.

Next Article

Debugging and Testing React ->

nexcoding.in