У меня есть родительский компонент под названием SettingsPage, и на этой странице может быть один из нескольких дочерних компонентов в зависимости от того, что такое tab.
Вот упрощенный пример моей текущей страницы:
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.info('user settings saved');
return (
<div>User Settings</div>
)
};
/* feedSettings.jsx */
const FeedSettings = () => {
const onSave = () => console.info('feed settings saved');
return (
<div>Feed Settings</div>
)
};
/* privacySettings.jsx */
const PrivacySettings = () => {
const onSave = () => console.info('privacy settings saved');
return (
<div>Privacy Settings</div>
)
};
В нижнем колонтитуле родительского компонента у меня есть кнопка сохранения, при нажатии на которую должна запускаться функция onSave соответствующего дочернего компонента. Я не хочу помещать логику сохранения в родительский компонент, поскольку все изменения происходят в дочернем компоненте.
Как правильно это сделать?
Да, правильный способ - поднять свое состояние. В противном случае вы можете использовать пример useImperativeHandle() -
Полностью повторяя эти комментарии, принятый ответ работает, но это не «простой» способ отреагировать. Это трудный путь, это перевернутая реакция. Родители не должны «запускать» функции у детей (в большинстве случаев). Если вы начнете помещать состояние в эти дочерние компоненты, это будет становиться все сложнее и сложнее. Альтернативой передаче всех вещей родительскому элементу является простое перемещение кнопки JSX в каждого из дочерних элементов. Осмысление того, как React хочет, чтобы вы писали код, одновременно сложно и важно для написания хорошего кода React.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Пользовательские настройки.js:
import React, { useImperativeHandle, forwardRef } from 'react';
const UserSettings = forwardRef((props, ref) => {
const onSave = () => console.info('user settings saved');
// This will expose the onSave method to the parent component via ref
useImperativeHandle(ref, () => ({
onSave
}));
return <div>User Settings</div>;
});
НастройкиПейдж.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>
);
};
Спасибо, это именно то, что я искал! Хотя синтаксис немного неясен, но я думаю, это просто особенность React.
Пожалуйста, рад, что смог помочь. Ха-ха, реакция — это весело, когда дело касается синтаксиса.
Вытащите логику сохранения из компонентов, и тогда вы сможете звонить, когда захотите. Например. Создайте функцию
saveFeed, а затем назначьте ее своей кнопке, и тогда вы также сможете вызвать родительский элемент.