Как передать данные от дочернего компонента в родительский в React TypeScript

Короткий ответ: в React дочерний компонент не меняет родителя напрямую. Родитель хранит состояние и передает в дочерний компонент callback-функцию. Дочерний компонент вызывает эту функцию и передает данные наверх

Схема:

Parent хранит state
Parent передает onChange в Child
Child вызывает onChange(value)
Parent обновляет state

Минимальный пример

Parent.tsx:

import { useState } from "react";
import { NameInput } from "./NameInput";

export function Parent() {
  const [name, setName] = useState("");

  return (
    <div>
      <NameInput onNameChange={setName} />
      <p>Имя: {name}</p>
    </div>
  );
}
type NameInputProps = {
  onNameChange: (value: string) => void;
};

export function NameInput({ onNameChange }: NameInputProps) {
  return (
    <input
      onChange={(event) => onNameChange(event.target.value)}
      placeholder="Введите имя"
    />
  );
}

Здесь Parent владеет состоянием name, а NameInput только сообщает новое значение

Почему не нужно менять parent напрямую

В React данные обычно идут сверху вниз: родитель передает props дочерним компонентам. Если child должен повлиять на parent, он не берет state родителя силой, а вызывает функцию, которую родитель сам передал

Так код остается предсказуемым:

state живет в одном месте
child не знает внутренности parent
обновление проходит через явный callback

Передача объекта

Можно передавать не строку, а объект:

type UserFormData = {
  name: string;
  email: string;
};

type UserFormProps = {
  onSubmit: (data: UserFormData) => void;
};

export function UserForm({ onSubmit }: UserFormProps) {
  function handleSubmit() {
    onSubmit({
      name: "Dinar",
      email: "dinar@example.com",
    });
  }

  return <button onClick={handleSubmit}>Сохранить</button>;
}

В родителе:

export function Parent() {
  function handleUserSubmit(data: UserFormData) {
    console.log(data.email);
  }

  return <UserForm onSubmit={handleUserSubmit} />;
}

Если структура объекта изменится, TypeScript подсветит места, где callback вызывается неправильно

Типизация события input

Если обработчик вынесен отдельно:

import type { ChangeEvent } from "react";

function handleChange(event: ChangeEvent<HTMLInputElement>) {
  onNameChange(event.target.value);
}

Для textarea будет HTMLTextAreaElement, для selectHTMLSelectElement. Не ставьте any, иначе можно случайно обратиться к несуществующему полю

Когда поднимать state выше

Если данные нужны только внутри дочернего компонента, не поднимайте их. Но если значение нужно родителю, соседнему компоненту или отправке формы, state лучше хранить на ближайшем общем уровне

Пример:

Parent
  SearchInput
  ResultsList

SearchInput меняет поисковую строку, а ResultsList показывает результат. Значит, строка должна жить в Parent

Частые ошибки

Первая ошибка — передавать результат вызова вместо функции:

<Child onChange={setName("Dinar")} />

Правильно:

<Child onChange={setName} />

Вторая ошибка — мутировать объект из props

Третья ошибка — использовать any для callback

Четвертая ошибка — хранить один и тот же state и в parent, и в child. Потом значения начинают расходиться

Пятая ошибка — называть callback слишком общо: onClick, хотя он передает email или всю форму. Лучше onEmailChange, onUserSubmit, onFilterChange

Самопроверка

Сделайте компонент CounterButton, который принимает onCountChange: (count: number) => void. Внутри child увеличивайте локальный счетчик и отправляйте новое значение родителю. Если TypeScript запрещает передать строку вместо числа, типизация работает

Что почитать дальше по TypeScript

Если нужен общий маршрут по теме, откройте рубрику TypeScript. Для соседних задач пригодятся эти разборы:

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x