Registry
M

moveStateToChildComponent

No description available

manishjha-040 executions

  • Legacy
  • React
Connect a repo
npx codemod moveStateToChildComponent

This codemod refactors React components by moving useState hooks from parent components to child components when the state and setter function (setState) are passed down as props. The goal is to simplify the parent components and allow child components to manage their own internal state when appropriate.

You can find the implementation of this codemod in the Studio here

Example

Case 1: Basic Prop Drilling

Before:

ts
function Parent() {
  const [count, setCount] = useState(0);

  return <Child count={count} setCount={setCount} />;
}

function Child({ count, setCount }) {
  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

After:

ts
function Parent() {
  return <Child />;
}

function Child() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

Case 2: Handling Destructured Props

Before:

ts
function Parent() {
  const [rating, setRating] = useState(null);

  return (
    <>
      <h1>Product</h1>
      <ProductRating rating={rating} setRating={setRating} />
    </>
  );
}

function ProductRating({ rating, setRating }) {
  return (
    <>
      <label htmlFor="rating">Rating</label>
      <input
        type="number"
        id="rating"
        onChange={(e) => setRating(parseInt(e.target.value))}
      />
      {rating && <p>Rating is {rating}</p>}
    </>
  );
}

After:

ts
function Parent() {
  return (
    <>
      <h1>Product</h1>
      <ProductRating />
    </>
  );
}

function ProductRating() {
  const [rating, setRating] = useState(null);

  return (
    <>
      <label htmlFor="rating">Rating</label>
      <input
        type="number"
        id="rating"
        onChange={(e) => setRating(parseInt(e.target.value))}
      />
      {rating && <p>Rating is {rating}</p>}
    </>
  );
}

Case 3: Conditional Rendering

The codemod does not move useState hooks in parent components if the child component is conditionally rendered. This is to avoid breaking logic that depends on certain conditions being met for state management.

Before:

ts
function Parent() {
  const [count, setCount] = useState(0);

  return (
    <div>
      {condition ? (
        <Child count={count} setCount={setCount} />
      ) : (
        <OtherChild />
      )}
    </div>
  );
}

function Child({ count, setCount }) {
  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

After:

ts
function Parent() {
  const [count, setCount] = useState(0);

  return (
    <div>
      {condition ? (
        <Child count={count} setCount={setCount} />
      ) : (
        <OtherChild />
      )}
    </div>
  );
}

function Child({ count, setCount }) {
  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

Ready to evolve your codebase?

Build tailored, compiler-aware skills to assess, plan, and automate complex codebase changes.