I have a parent component called SettingsPage, and in that page there could be one of several different child components depending on what tab is.
Here’s the simplified example of my current page:
const SettingsPage = () => {
const [tab, setTab] = useState('user');
return (
<div className="settings-page">
<div className="content">
{tab === 'user' && <UserSettings />}
{tab === 'feed' && <FeedSettings />}
{tab === 'privacy' && <PrivacySettings />}
</div>
<footer>
{ /* how do I trigger onSave function of the child components? */ }
<button className="btn btn-save">Save</button>
</footer>
</div>
)
}
/* userSettings.jsx */
const UserSettings = () => {
const onSave = () => console.log('user settings saved');
return (
<div>User Settings</div>
)
};
/* feedSettings.jsx */
const FeedSettings = () => {
const onSave = () => console.log('feed settings saved');
return (
<div>Feed Settings</div>
)
};
/* privacySettings.jsx */
const PrivacySettings = () => {
const onSave = () => console.log('privacy settings saved');
return (
<div>Privacy Settings</div>
)
};
In the footer of the parent component, I have a save button, that I want it upon clicking, the corresponding child component’s onSave function should be triggered. I don’t want to put the save logic in the parent component since all changes are happening in child component.
What is the proper way to do it?
>Solution :
- Define a Forwarded Ref for Each Child Component.
- Use useImperativeHandle in Child Components.
- Manage Refs in the Parent Component.
UserSettings.js:
import React, { useImperativeHandle, forwardRef } from 'react';
const UserSettings = forwardRef((props, ref) => {
const onSave = () => console.log('user settings saved');
// This will expose the onSave method to the parent component via ref
useImperativeHandle(ref, () => ({
onSave
}));
return <div>User Settings</div>;
});
SettingsPage.js:
import React, { useState, useRef } from 'react';
import UserSettings from './UserSettings'; // Import your components
import FeedSettings from './FeedSettings';
import PrivacySettings from './PrivacySettings';
const SettingsPage = () => {
const [tab, setTab] = useState('user');
const activeComponentRef = useRef(null);
const onSaveClick = () => {
if (activeComponentRef.current) {
activeComponentRef.current.onSave();
}
};
return (
<div className="settings-page">
<div className="content">
{tab === 'user' && <UserSettings ref={activeComponentRef} />}
{tab === 'feed' && <FeedSettings ref={activeComponentRef} />}
{tab === 'privacy' && <PrivacySettings ref={activeComponentRef} />}
</div>
<footer>
<button className="btn btn-save" onClick={onSaveClick}>Save</button>
</footer>
</div>
);
};