Props Immutability
In React, components should treat received props as read-only inputs rather than modifying them. When a child needs a change, it should communicate the request through a callback so the owner can update state and pass new props.
Props are values passed from a parent component to a child component. They describe the child's inputs for a render and should be treated as immutable by the receiving component.
A child should not assign a new value to a prop or mutate an object or array stored inside a prop. Mutating nested data can be especially subtle because the reference itself may remain unchanged, making updates harder to reason about and potentially preventing expected React updates.
When a child needs to cause a change, the usual pattern is to keep the changing data in the component that owns it and pass a callback such as `onChange` or `onDelete` to the child. The child calls that function with the information needed for the parent to update its state.
This creates a one-way data flow: the parent owns state, passes values down as props, and receives change requests through callbacks. The pattern makes component behavior easier to predict and keeps ownership of data clear.
Key points
- Treat props as read-only inputs.
- Do not assign to props or mutate objects and arrays received through props.
- Use callbacks to communicate requested changes to the parent.
- Keep mutable application state in the component responsible for owning that state.
- Prefer immutable state updates so React can observe changed references.
Interview questions
Can a React component modify its props?
A component should treat its props as read-only and should not modify them. Props belong to the component that passes them. If a child needs a value to change, it should call a callback supplied by the parent. The parent can then update its state and render the child with new props.
Why is mutating an object received through props problematic?
An object prop is passed by reference, so changing one of its fields changes the existing object rather than producing a new object. This can make data ownership unclear and can interfere with React patterns that rely on reference changes to detect updates. It also means other code holding the same object can observe the mutation unexpectedly. Instead, create a new object and let the owner update its state.
How should a child request a change to data owned by its parent?
The parent can pass a callback prop to the child. The child invokes that callback with the relevant value or action instead of changing the data directly. The parent handles the callback by updating its state. React then renders the child again with the updated value as a prop.
What does one-way data flow mean in a React component hierarchy?
Data generally flows from a component that owns state down to descendants through props. A descendant can communicate upward by invoking a callback supplied by an ancestor. The ancestor remains responsible for changing the state. This separates displaying data from owning and changing that data.
If a child receives an array prop and needs to add an item, what pattern should you use?
The child should not call methods that mutate the received array, such as `push`. Instead, it should notify the owner through a callback, and the owner should create a new array containing the added item. For example, the owner can use a state updater with `[...items, newItem]`. This preserves the ownership boundary and gives React a new array reference.