Props flow in one direction only, from parent to child, and are passed just like HTML attributes, though any value type can be passed via curly braces, not just strings — a component receives all its props bundled into a single object as its first function argument. Props are strictly read-only from the receiving component's perspective; a component must never modify its own props directly, since React relies on props staying immutable to reliably detect when a re-render is actually necessary.
1Understanding Props
Props flow in one direction only, from parent to child, and are passed just like HTML attributes, though any value type can be passed via curly braces, not just strings — a component receives all its props bundled into a single object as its first function argument. Props are strictly read-only from the receiving component's perspective; a component must never modify its own props directly, since React relies on props staying immutable to reliably detect when a re-render is actually necessary.
Never modify a prop's value directly inside the component that received it — props are meant to be read-only, and mutating one directly can produce confusing, hard-to-track bugs since the parent component remains unaware its data was changed.
function Greeting({ name, age }) {
return <p>{name} is {age} years old.</p>;
}
function App() {
return <Greeting name="Ana" age={30} />;
}2Practical Example
Here is a real-world application of Props showing how it is used in production React code.
function Button({ label, onClick }) {
return <button onClick={onClick}>{label}</button>;
}
function App() {
const handleClick = () => console.log('Clicked!');
return <Button label="Submit" onClick={handleClick} />;
}3Best Practices
Follow these guidelines when working with Props:
1. Treat every prop as strictly read-only inside the receiving component, copying it into local state first if you need a modifiable version
2. Use destructuring, function MyComponent({ name, age }), to access props cleanly rather than repeatedly writing props.name, props.age
3. Provide default values for optional props, either via default parameters in destructuring or a defaultProps property, so the component behaves sensibly when a prop is omitted
Tip: Never modify a prop's value directly inside the component that received it — props are meant to be read-only, and mutating one directly can produce confusing, hard-to-track bugs since the parent component remains unaware its data was changed.
function Greeting({ name, age }) {
return <p>{name} is {age} years old.</p>;
}
function App() {
return <Greeting name="Ana" age={30} />;
}4Default Values for Props
A destructured parameter can specify a default value directly: function Button({ variant = 'primary' }). The default kicks in only when the prop is omitted entirely, or explicitly passed as undefined — passing null does not trigger it, since null is treated as a deliberately provided value.
function Button({ variant = 'primary', children }) {
return <button className={variant}>{children}</button>;
}
<Button>Save</Button>5Spreading Props
When a component needs to forward most of its received props unchanged to an underlying element, the spread syntax passes every property of an object as individual props in one line: <input {...inputProps} />. Explicit props listed after the spread override any same-named prop from the spread object.
function TextField(props) {
return <input className="field" {...props} />;
}
<TextField placeholder="Email" type="email" />