Controlling Child Component State from a Parent in React
Today I stumbled into a fun little React problem while working with forwardRef and useImperativeHandle. I had a simple input component that needed to expose some methods—like .focus() and .clear()—to the parent. Easy enough, right?
But then I hit the next question: "Wait… what if I want the parent to access or update the internal state of this child?"
Here’s how it started:
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
const MyInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus(),
clear: () => { inputRef.current.value = ''; },
}));
return <input ref={inputRef} />;
});
Pretty straightforward. But I realized this input isn't even using React state—it's just directly manipulating the DOM. So what if we want to store the input’s value in a state and give the parent full control over it?
🧠 Solution: Expose state methods with useImperativeHandle
React doesn’t allow parents to directly "see" into a child’s state (for good reason!), but we can selectively expose getters and setters through the ref.
Here’s how that looks:
Recommended by LinkedIn
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react';
const MyInput = forwardRef((props, ref) => {
const [value, setValue] = useState('');
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus(),
clear: () => setValue(''),
getValue: () => value,
setValue: (val) => setValue(val),
}));
return (
<input
ref={inputRef}
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
});
Now in the parent, we can do this:
const Parent = () => {
const inputRef = useRef();
return (
<>
<MyInput ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>Focus</button>
<button onClick={() => inputRef.current.clear()}>Clear</button>
<button onClick={() => alert(inputRef.current.getValue())}>Get Value</button>
<button onClick={() => inputRef.current.setValue('Updated from parent!')}>Set Value</button>
</>
);
};
💡 Takeaway
useImperativeHandle isn’t just for DOM access—it's your window into exposing custom logic or controlled state from a child to a parent, without breaking the encapsulation React gives you by default.
This pattern comes in handy when you're working with reusable input components, modals, or anything that needs to be controlled externally in a more declarative React-style way.
#React #JavaScript #FrontendDevelopment #radikadilanka #TodayILearned
Associate Software Engineer at TWC Innovations | Full Stack Developer | React | Next | Node | Python | Typescript | WordPress
3wDefinitely worth reading