Questions
A child component is failing to update the parent's state. Why is this happening and how do you fix it?
A junior developer has built a UserProfile component that displays a username. They’ve also created a ChangeUsername child component that should update the username in the parent when a button is clicked.
However, clicking the button does nothing. The parent’s state isn’t updating.
Your task is to identify the bug that breaks React’s one-way data flow and fix the code so that clicking the button correctly updates the username displayed in the UserProfile component.
import React, { useState } from 'react';
// Child component that tries to modify the prop directly
function ChangeUsername({ username }) {
const changeName = () => {
// This is the bug! Props are read-only.
// This will not update the parent's state.
username = 'Bob';
console.log(`Username in child changed to: ${username}`);
};
return (
<button onClick={changeName}>
Change Username to Bob
</button>
);
}
// Parent component
export default function UserProfile() {
const [username, setUsername] = useState('Alice');
return (
<div>
<h1>Welcome, {username}!</h1>
<ChangeUsername username={username} />
</div>
);
} The child component attempts to directly mutate the `username` prop by reassigning it. In React, props are read-only and cannot be modified by child components. The reassignment only affects the local variable inside the function and doesn't update the parent's state or trigger a re-render.
The parent component should pass down a callback function (like `onUsernameChange`) as a prop. The child calls this function to signal that a state change is needed. The parent owns both the state and the function that modifies it, following React's 'lifting state up' pattern and maintaining one-way data flow.
The bug occurs because the child component tries to directly mutate the username prop. In React, this is an anti-pattern. Data flows in one direction: from parent to child. Props are read-only and cannot be modified by the child component.
The console.log shows the local username variable inside the changeName function being reassigned, but this does not affect the username state in the UserProfile parent component. React has no knowledge of this mutation, so it does not trigger a re-render.
Here is the corrected implementation:
import React, { useState } from 'react';
// Child component now receives a function to call
function ChangeUsername({ onUsernameChange }) {
return (
<button onClick={() => onUsernameChange('Bob')}>
Change Username to Bob
</button>
);
}
// Parent component
export default function UserProfile() {
const [username, setUsername] = useState('Alice');
// The parent manages the state and the logic to update it
const handleUsernameChange = (newName) => {
setUsername(newName);
console.log(`Username updated to: ${newName}`);
};
return (
<div>
<h1>Welcome, {username}!</h1>
<ChangeUsername onUsernameChange={handleUsernameChange} />
</div>
);
} Practice Question
In a React application, what is the standard way to manage data flow?