React Props and React State — A Complete Guide (2025)
September 17, 2022
React's strength lies in how it manages data flow inside applications. Whether you're building reusable UI components or large-scale React applications, understanding props and state is essential. These two core concepts define how data is passed, updated, and rendered throughout the React component lifecycle.
Since 2022, React has evolved significantly with React 18 concurrent features, improved React hooks, enhanced Context API, and React Server Components. This comprehensive React tutorial explains what props and state are, how they differ, and the React best practices every frontend developer should follow in 2025.
What Are Props and State?
Props (Properties)
- Inputs passed from parent to child components.
- Immutable (read-only inside the child).
- Used for configuration, rendering data, and communication.
- Examples:
title,user,onClickcallbacks.
State
- Data that a component owns and controls.
- Mutable, updated with hooks like
useStateoruseReducer. - Used for interactive behavior: toggles, forms, fetching data, UI updates.
- Example: form field values, modal open/close status, or a counter.
Props vs. State: Key Differences
| Aspect | Props | State |
|---|---|---|
| Ownership | Passed down from parent | Maintained inside the component |
| Mutability | Read-only | Can be updated with hooks |
| Purpose | Configure components, pass data & logic | Track and manage local changes |
| Updates trigger | Re-renders when parent re-renders | Re-renders when state changes |
Modern React: Updated Usage
In modern React development, functional components with hooks have replaced class-based patterns. Here's how React state management works today.
The useState Hook
Instead of this.setState in class components, React functional components use the useState hook:
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
React Context API for Prop-Drilling Problems
The React Context API solves prop drilling—avoid passing props through multiple component layers:
import { createContext, useContext } from "react";
const ThemeContext = createContext("light");
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
const theme = useContext(ThemeContext);
return <button className={theme}>Themed Button</button>;
}
React 18+ Improvements
- Automatic Batching: multiple state updates are batched for performance.
- Transitions: smoother UI updates for concurrent rendering.
- Server Components: some props/state considerations shift to hybrid rendering.
React Best Practices (2025 Edition)
These React performance optimization tips and patterns help you build maintainable, scalable applications:
- Keep state minimal — store only what you can't derive from props or other state.
- Lift state up only when multiple children need access—a core React design pattern.
- Use context or global stores (Redux Toolkit, Zustand, Jotai, TanStack Query) for complex React state management.
- Type your props with TypeScript for better developer experience and fewer bugs.
- Prevent unnecessary re-renders — use
React.memo,useCallback, anduseMemostrategically. - Always use immutable updates — never mutate arrays or objects directly.
- Clean up side effects — always return cleanup functions from
useEffecthooks.
Example: Combining Props, State, and Context
import React, { useState, useCallback, createContext, useContext } from "react";
import PropTypes from "prop-types";
const ThemeContext = createContext();
function App() {
const [count, setCount] = useState(0);
const increment = useCallback(() => setCount(c => c + 1), []);
return (
<ThemeContext.Provider value="dark">
<Counter count={count} onIncrement={increment} />
</ThemeContext.Provider>
);
}
function Counter({ count, onIncrement }) {
const theme = useContext(ThemeContext);
return (
<div style={{ color: theme === "dark" ? "#fff" : "#000" }}>
<p>You clicked {count} times</p>
<button onClick={onIncrement}>Increment</button>
</div>
);
}
Counter.propTypes = {
count: PropTypes.number.isRequired,
onIncrement: PropTypes.func.isRequired,
};
export default App;
Conclusion
Props and state are the cornerstones of React development. By combining them with React hooks, the Context API, and React 18 concurrent features, you'll build applications that are both performant and scalable.
Mastering these React fundamentals prepares you for advanced patterns—including React Server Components, global state management with Zustand or Redux, and React performance optimization techniques.
Whether you're building a Next.js application, a Create React App project, or a Vite React setup, these concepts remain essential. Keep practicing with real projects and stay updated with the evolving React ecosystem.