React Props vs State Explained for Beginners (With Examples)
Confused about React props vs state? This beginner guide breaks down the difference with plain-English explanations, code examples, and a comparison table.
Confused about React props vs state? This beginner guide breaks down the difference with plain-English explanations, code examples, and a comparison table.
In one sentence: props are data a component receives from its parent, and state is data a component manages and can change on its own. Props are read-only. State can be updated with a special function, and updating it makes React redraw the component. If you have ever felt stuck deciding which one to use, this guide will clear it up with plain-English explanations and small code examples you can copy and run.
This guide assumes you already know basic JavaScript, like variables and functions. If some of that feels shaky, it may help to read our guide on JavaScript variables and data types first, then come back here.
React is a JavaScript library for building user interfaces out of small, reusable pieces called components. A component is just a JavaScript function that returns some markup, written in a syntax called JSX (JavaScript XML). Here is the smallest possible component:
function Welcome() {
return <h1>Hello, world!</h1>;
}Line by line: `function Welcome()` declares a normal JavaScript function. React component names must start with a capital letter, so `Welcome` works but `welcome` would not. The function returns `<h1>Hello, world!</h1>`, which looks like HTML but is actually JSX - React turns it into a real HTML heading on the page. Every component must return exactly one block of markup like this.
Props (short for "properties") are how a parent component sends data into a child component, similar to how you pass arguments into a JavaScript function. The child component can read the data but cannot change it - props always flow one way, from parent to child.
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
function App() {
return <Welcome name="Maria" />;
}Here is what each part does: `Welcome(props)` now accepts a `props` argument, which React fills in automatically. Inside the JSX, `{props.name}` uses curly braces to drop a JavaScript value into the markup - this reads the `name` value out of the `props` object. In the `App` component, `<Welcome name="Maria" />` renders the `Welcome` component and passes it a prop called `name` with the value `"Maria"`. The result on the page is `Hello, Maria!`. If `App` rendered `<Welcome name="Sam" />` instead, the page would say `Hello, Sam!` - the same component, reused with different data.
State is data that a component owns and can change over time, such as text typed into an input box or a counter that goes up when a button is clicked. Unlike props, a component is allowed to update its own state. In modern React, you create state with the `useState` hook - a hook is simply a special function that starts with `use` and lets a function component "hook into" React features.
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}Breaking this down: `import { useState } from "react"` brings in the `useState` hook so we can use it. `const [count, setCount] = useState(0)` creates a piece of state called `count`, starting at `0`, and gives us a function called `setCount` to update it - `useState` always returns an array with exactly two items: the current value and a setter function. Inside the markup, `{count}` displays the current value. The button has an `onClick` handler that runs `setCount(count + 1)` every time it is clicked. Calling the setter does two things: it updates the stored value, and it tells React to re-render the component so the new number shows up on screen immediately.
| Question | Props | State |
|---|---|---|
| Where does the data come from? | Passed in by a parent component | Created and stored inside the component itself |
| Can the component change it? | No, props are read-only | Yes, using the setter function from useState |
| What is it used for? | Configuring or customizing a component | Tracking data that changes, like form input or a counter |
| What happens when it changes? | The parent passes new props, and the child re-renders | Calling the setter re-renders the component that owns the state |
A very common use of state is storing what a user types into a form. This is called a "controlled input", because React state controls the value shown in the input box.
import { useState } from "react";
function NameForm() {
const [name, setName] = useState("");
function handleSubmit(event) {
event.preventDefault();
alert(`Hello, ${name}!`);
}
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={name}
onChange={(event) => setName(event.target.value)}
/>
<button type="submit">Say hello</button>
</form>
);
}Here, `const [name, setName] = useState("")` creates state that starts as an empty string. The `<input>` element's `value={name}` means the box always shows whatever is stored in state. The `onChange` handler runs on every keystroke and calls `setName(event.target.value)`, which reads the text currently in the box and saves it into state - this is what keeps the input and the state in sync. `handleSubmit` runs when the form is submitted; `event.preventDefault()` stops the browser from reloading the page, which is the default behavior for forms, and then we show an alert using the current `name` value.
Props are often used to hand a component a list of data to display. Here, the parent owns the array, and the child just receives it and renders it.
function FruitList({ fruits }) {
return (
<ul>
{fruits.map((fruit) => (
<li key={fruit}>{fruit}</li>
))}
</ul>
);
}
function App() {
return <FruitList fruits={["Apple", "Banana", "Mango"]} />;
}`function FruitList({ fruits })` uses destructuring to pull the `fruits` prop straight out of the props object, instead of writing `props.fruits` every time. Inside the JSX, `fruits.map((fruit) => ...)` loops over the array and returns one `<li>` element per fruit. Each `<li>` needs a `key` prop, which is a unique value that helps React keep track of list items efficiently when the list changes - here we use the fruit name itself, since each one is unique. In `App`, the array `["Apple", "Banana", "Mango"]` is passed in as the `fruits` prop, and `FruitList` never modifies it - it just displays it.
Want a refresher on the JavaScript basics that React builds on, like variables and data types?
Read the JavaScript beginner guideProps are data passed into a component from its parent, and they are read-only. State is data that a component creates and manages itself, and it can be updated using a setter function, such as the one returned by useState. When either changes, React re-renders the affected component.
No. Props must be treated as read-only inside the component that receives them. If a value needs to change, either the parent component should update the prop it passes down, or the value should be stored in state instead.
Use state when a component needs to track information that changes over time and that it owns itself, like text in a form field, a counter, or whether a menu is open. Use props when a parent component needs to configure or supply data to a child component.
useState is a built-in React hook that adds state to a function component. It returns an array with two items: the current value and a function to update it, for example const [count, setCount] = useState(0). Calling the update function changes the value and tells React to re-render the component.
Yes. React is a JavaScript library, so you should be comfortable with JavaScript basics first, including variables, functions, arrays, and the map() method, since these show up constantly in React code.
Props and state are the two core ways data flows through a React app: props carry data down from parent to child, and state lets a component manage its own changing data. Once this distinction feels natural, the rest of React - forms, lists, and hooks - starts to make a lot more sense.
Building a product and want an experienced team to help you ship it?
Talk to FepiqOccasional, no-fluff notes on shipping modern software — startups, automation, Laravel, Shopify and more. No spam, unsubscribe anytime.
Keep reading
What is an index in SQL? A plain-English guide with copy-paste examples showing how indexes speed up queries and when you actually need one.
Learn JavaScript DOM manipulation for beginners: select elements, change text and styles, and handle clicks with simple, copy-paste code examples.
Let's build something
Book a free discovery call. We'll listen, ask sharp questions, and send you a proposal within 3 business days.