![]()
Mutating props inside a child component in React is a common mistake that can lead to unpredictable behavior, bugs, and issues with React’s unidirectional data flow. Props are meant to be immutable within the child component, as they are passed down from parent components.
Common Causes & Fixes:
- Incorrect: Directly Mutating Props
- Incorrect:
function ChildComponent(props) { props.name = "New Name"; // Direct mutation of props (not allowed) return <h1>{props.name}</h1>; } - Fix: Use a local variable to handle changes or trigger a callback to the parent:
function ChildComponent(props) { const newName = props.name + " Updated"; // Use local variable return <h1>{newName}</h1>; }
- Incorrect:
- Incorrect: Modifying Nested Objects or Arrays in Props
- Incorrect:
function ChildComponent(props) { props.user.details.age = 30; // Mutating nested object return <h1>{props.user.details.age}</h1>; } - Fix: Create a copy of the nested object before modifying it:
function ChildComponent(props) { const updatedUser = { ...props.user, details: { ...props.user.details, age: 30 } }; return <h1>{updatedUser.details.age}</h1>; }
- Incorrect:
- Incorrect: Using
propswithsetState()in Class Components- Incorrect:
class ChildComponent extends React.Component { constructor(props) { super(props); this.state = { name: props.name }; this.state.name = "New Name"; // Direct mutation } render() { return <h1>{this.state.name}</h1>; } } - Fix: Use
setState()to update local state if needed, but don’t mutateprops:class ChildComponent extends React.Component { constructor(props) { super(props); this.state = { name: props.name }; } updateName = () => { this.setState({ name: "New Name" }); }; render() { return ( <div> <h1>{this.state.name}</h1> <button onClick={this.updateName}>Change Name</button> </div> ); } }
- Incorrect:
- Incorrect: Changing Props Directly in
useEffect(Functional Components)- Incorrect:
function ChildComponent({ name }) { React.useEffect(() => { name = "Updated Name"; // Mutation inside useEffect (not allowed) }, []); return <h1>{name}</h1>; } - Fix: Use
useStatefor local changes or trigger a callback to the parent:function ChildComponent({ name }) { const [localName, setLocalName] = React.useState(name); React.useEffect(() => { setLocalName("Updated Name"); // Proper state update }, []); return <h1>{localName}</h1>; }
- Incorrect:
Correct Example:
import React from 'react';
function ChildComponent({ name }) {
return <h1>{name}</h1>; // Display props without mutation
}
function ParentComponent() {
const user = { name: "John Doe" };
return <ChildComponent name={user.name} />;
}
export default ParentComponent;
Why This Matters:
- Props are read-only and should not be modified by child components.
- Modifying props can lead to unexpected UI behavior, bugs, and state inconsistencies.
- React’s data flow relies on the idea that the parent manages the state and the child receives data as-is.
Best Practices:
- Use
propsfor passing data down the component tree. - If data needs to be changed, trigger a callback to the parent or manage it in the component’s local state.
- Avoid side effects that mutate props in
useEffector lifecycle methods.
