My 7-Day Journey with React: An In-Depth Look at Key Concepts, Hooks, and Best Practices
React has revolutionized how developers build user interfaces by simplifying DOM manipulation and optimizing state management. In this article, I’ll walk you through my day-by-day experience, covering everything from fundamental concepts to complex state handling and advanced hooks.
Day 1: The Foundation - Understanding React’s Core Functions
Primary Functions of React
React serves two fundamental purposes:
DOM Manipulation Made Easy: React uses JSX (JavaScript XML) to make HTML-like syntax available within JavaScript, enabling seamless DOM manipulation. This eliminates the need for cumbersome JavaScript methods like
createElement
orinnerHTML
. React’sReactDOM
library further simplifies the process by handling how elements are inserted into the DOM.Efficient State Management: React enables intelligent state-based rendering. When the state of an app changes, React automatically re-renders only the affected parts of the DOM, which enhances performance. This is achieved by maintaining a virtual representation of the DOM, comparing it with the real DOM, and updating only the necessary parts.
Example - Basic JSX and State
javascriptCopy codeimport React, { useState } from 'react';
function App() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default App;
Pitfalls on Day 1
Forgetting JSX Syntax: JSX isn’t HTML; it has its quirks. For instance, use
className
instead ofclass
in JSX. Missing these details often led to errors.Not Grasping State’s Role: It’s easy to misinterpret state as just another variable, but in React, state is central to reactivity and rendering. Using state correctly involves understanding how it triggers re-renders.
Day 2: Mastering JSX and React DOM
JSX and ReactDOM in Action
JSX lets us write HTML-like elements within JavaScript. It’s not just syntactic sugar but is transformed into JavaScript code (e.g., React.createElement
). Here’s how JSX and ReactDOM make DOM manipulation efficient:
ReactDOM takes care of rendering React components to the actual DOM.
JSX helps blend HTML and JavaScript, so developers can write UI code within a single file.
Example - JSX and ReactDOM
javascriptCopy codeimport ReactDOM from 'react-dom';
function Greeting() {
return <h1>Hello, world!</h1>;
}
ReactDOM.render(<Greeting />, document.getElementById('root'));
Pitfalls
- Ignoring JavaScript Code in JSX: JSX lets you use expressions within
{}
, but it doesn’t support statements. Trying to use statements likeif
can cause syntax errors; instead, use conditional expressions.
Day 3: The Power of useState and setState for State Management
State Management with useState
In React, state refers to the data that controls the component’s behavior. Using useState
, you can create a piece of state and a function to update it.
Example - Counter with useState
javascriptCopy codeimport React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
Pitfalls
- Relying on Stale State: When updating state based on the previous state, using the function form of
setState
(e.g.,setCount(prevCount => prevCount + 1)
) helps prevent bugs, especially when dealing with asynchronous updates.
Day 4: Deeper into State Changes - The Importance of Top-Level State and setState
To ensure efficient rendering, React expects state to be managed at the top level of the component. This structure enables the component and its children to be efficiently re-rendered when the state changes.
Common Pitfall
- Updating State in Nested Functions: State changes should be managed at the component’s top level to avoid unnecessary re-renders and to ensure all affected child components respond correctly.
Example - setState at the Top Level
javascriptCopy codeimport React, { useState } from 'react';
function ParentComponent() {
const [parentState, setParentState] = useState("Hello");
return (
<div>
<ChildComponent parentState={parentState} />
<button onClick={() => setParentState("Hi there!")}>Update Parent State</button>
</div>
);
}
function ChildComponent({ parentState }) {
return <p>{parentState}</p>;
}
Day 5: Introducing useEffect - Managing Side Effects
Understanding useEffect
useEffect
allows components to perform side effects like data fetching, setting up subscriptions, or changing the DOM. useEffect
runs after the initial render, and you can specify dependencies to control when it triggers.
Example - Fetching Data with useEffect
javascriptCopy codeimport React, { useState, useEffect } from 'react';
function FetchComponent() {
const [data, setData] = useState(null);
useEffect(() => {
fetch("https://api.example.com/data")
.then(response => response.json())
.then(data => setData(data));
}, []); // Runs only once, like componentDidMount
return <div>{data ? JSON.stringify(data) : "Loading..."}</div>;
}
Pitfall - Forgetting Dependencies
- Infinite Loops: Not including dependencies can lead to re-renders every time the component mounts. Always add the required state variables or props in the dependency array to avoid this.
Day 6: Building Complex Components - Single Element Return, Keys, and Memoization
Single Element Return and Keys
React requires components to return a single element. When rendering lists, React needs unique key
properties for each item to optimize updates and ensure elements are correctly matched in re-renders.
Example - List Rendering with Keys
javascriptCopy codeimport React from 'react';
function ListComponent({ items }) {
return (
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
Using React.memo for Memoization
React.memo
is a higher-order component that memoizes a component, preventing unnecessary re-renders when props haven’t changed.
Example - Optimizing with React.memo
javascriptCopy codeimport React from 'react';
const ExpensiveComponent = React.memo(({ data }) => {
console.log("Rendering Expensive Component");
return <div>{data}</div>;
});
Pitfall - Overusing React.memo
- Premature Optimization: Using
React.memo
on components that don’t have performance issues can add unnecessary complexity. Only apply memoization when profiling shows a real need.
Day 7: Best Practices and Common Mistakes to Avoid in React
Use
setState
Function Form for Dependent Updates: When updating state based on the previous state, always use the function form ofsetState
.Place State in the Right Components: When multiple components need the same state, consider lifting it to a common ancestor to avoid prop drilling and redundant updates.
Don’t Directly Mutate State: React relies on immutable data. Directly modifying an array or object in state can lead to bugs.
Understand JSX Limitations: JSX is more than just HTML inside JavaScript; it has its syntax (like
className
instead ofclass
andhtmlFor
instead offor
).Use Effects Wisely: Don’t overuse
useEffect
for simple UI updates. Overusing effects can slow down your app and create hard-to-debug issues.
Final Thoughts
React’s ability to simplify DOM manipulation and optimize reactivity through efficient state handling makes it incredibly powerful. Throughout this journey, I learned that React is best used with a deep understanding of state management, component structure, and hooks like useState
and useEffect
.
Subscribe to my newsletter
Read articles from rohit mantha directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by