DeployU
Interviews / Frontend Engineering / A child component is failing to update the parent's state. Why is this happening and how do you fix it?

Questions

A child component is failing to update the parent's state. Why is this happening and how do you fix it?

debugging Props & State Interactive Quiz Code Examples

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.

UserProfile - Fix Parent State Update
Your Code
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>
  );
}
// Validate the fix
const code = document.querySelector('[data-editor]').textContent;

// Check that child receives a callback function prop
if (!code.includes('onUsernameChange') && !code.includes('onChange') && !code.includes('onUpdate')) {
  throw new Error('Test failed: Pass a callback function as a prop (e.g., onUsernameChange) to the child component.');
}

// Check that parent defines a handler function
if (!code.includes('handleUsernameChange') && !code.includes('handleChange') && !code.includes('handleUpdate')) {
  throw new Error('Test failed: Create a handler function in the parent that calls setUsername.');
}

// Check that setUsername is called
if (!code.includes('setUsername')) {
  throw new Error('Test failed: The parent should use setUsername to update the state.');
}

// Success!
console.log('✓ All tests passed! Child can now update parent state via callback.');
console.log('✓ This follows React\'s one-way data flow pattern correctly.');
Click "Run Code" to see output...
Click "Run Code" to see test results...
Wrong Approach

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.

Right Approach

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?