Передача функций как props
Передача функций через props — ключевой паттерн в React для обеспечения взаимодействия между компонентами при сохранении одностороннего потока данных. Поскольку дочерние компоненты не могут напрямую изменять состояние родителя, они вызывают переданные функции-колбэки, чтобы запросить изменение.
Как передать функцию в дочерний компонент
Родительский компонент определяет функцию (обычно с использованием useState или других хуков) и передаёт её как prop:
function Parent() {
const [isVisible, setIsVisible] = useState(false);
return (
<TogglePanel onToggle={() => setIsVisible(!isVisible)} />
);
}
Дочерний компонент получает эту функцию и вызывает её в ответ на событие:
function TogglePanel({ onToggle }) {
return <button onClick={onToggle}>Переключить</button>;
}
Почему это важно
Такой подход сохраняет единственный источник истины: состояние остаётся в том компоненте, которому оно принадлежит. Дочерний компонент лишь сигнализирует о намерении изменить данные, не зная и не контролируя их внутреннюю структуру. Это делает компоненты более переиспользуемыми и тестируемыми.
Передача параметров в колбэк
Функции-props могут принимать аргументы, что особенно полезно в списках или формах:
function TodoList({ todos, onDelete }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.text}
<button onClick={() => onDelete(todo.id)}>Удалить</button>
</li>
))}
</ul>
);
}
// В родителе
<TodoList todos={todos} onDelete={(id) => setTodos(todos.filter(t => t.id !== id))} />
Здесь стрелочная функция () => onDelete(todo.id) оборачивает вызов, чтобы передать конкретный id.
Оптимизация: избегание лишних пересозданий
При каждом рендере родителя передаваемая функция создаётся заново, что может вызывать ненужные ререндеры дочерних компонентов. Для оптимизации используют useCallback:
const handleToggle = useCallback(() => setIsVisible(v => !v), []);
return <TogglePanel onToggle={handleToggle} />;
Это особенно актуально при использовании React.memo или в производительных сценариях.