Yes ✅, apart from using callback functions, there are a few alternative ways to pass data from child to parent in React:
🔸 1. Using Context API
- The parent provides context; the child updates shared context state.
- Useful for deeply nested components.
Example:
// Context.js
export const MyContext = createContext();
export const MyProvider = ({ children }) => {
const [data, setData] = useState('');
return (
<MyContext.Provider value={{ data, setData }}>
{children}
</MyContext.Provider>
);
};
// Parent.jsx
import { MyContext } from './Context';
const Parent = () => {
const { data } = useContext(MyContext);
return <h1>{data}</h1>;
};
// Child.jsx
import { MyContext } from './Context';
const Child = () => {
const { setData } = useContext(MyContext);
return <button onClick={() => setData('Updated!')}>Send</button>;
};
🔸 2. Using Global State Libraries
- Tools like Redux, Zustand, or Recoil allow shared state between any components, no matter the hierarchy.
🔸 3. Using Refs (Uncontrolled approach)
- The parent can pass a
refto the child and the child updates it. - Not recommended for complex data flow.
Example:
// Parent.jsx
const Parent = () => {
const inputRef = useRef();
const getData = () => alert(inputRef.current.value);
return (
<>
<Child inputRef={inputRef} />
<button onClick={getData}>Get Data</button>
</>
);
};
// Child.jsx
const Child = ({ inputRef }) => {
return <input ref={inputRef} />;
};
🔸 4. State Management via URL or LocalStorage (Edge Case)
- Rare, but possible when components are re-mounted or across routes.
✅ Best Practice:
- For simple apps → callback props.
- For deeply nested or complex apps → Context API or state libraries like Redux/Zustand.