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:
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:
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:
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><inputtype="number"id="rating"onChange={(e) => setRating(parseInt(e.target.value))}/>{rating && <p>Rating is {rating}</p>}</>);}
After:
function Parent() {return (<><h1>Product</h1><ProductRating /></>);}function ProductRating() {const [rating, setRating] = useState(null);return (<><label htmlFor="rating">Rating</label><inputtype="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:
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:
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>);}
Build custom codemods
Use AI-powered codemod studio and automate undifferentiated tasks for yourself, colleagues or the community