← Назад к вопросам

Как можно передавать данные между компонентами?

1.3 Junior🔥 191 комментариев
#React

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Передача данных между компонентами в React

В React существует несколько способов передачи данных между компонентами. Выбор метода зависит от типа связи и архитектуры приложения.

1. Props (родитель -> потомок)

Это базовый и наиболее часто используемый способ:

// Родительский компонент
const Parent = () => {
  const data = 'Привет из родителя';
  
  return <Child message={data} />;
};

// Дочерний компонент
const Child = ({ message }) => (
  <div>{message}</div>
);

2. Props drilling (передача через промежуточные компоненты)

// Уровень 1
const Level1 = () => {
  const data = 'Важная информация';
  return <Level2 data={data} />;
};

// Уровень 2 (просто пробрасываем далее)
const Level2 = ({ data }) => {
  return <Level3 data={data} />;
};

// Уровень 3 (используем)
const Level3 = ({ data }) => {
  return <div>{data}</div>;
};

// Проблема: много промежуточных компонентов
// Решение: использовать Context API

3. Context API (глобальное состояние)

import { createContext, useContext, useState } from 'react';

// 1. Создаем контекст
const UserContext = createContext();

// 2. Создаем провайдер
const UserProvider = ({ children }) => {
  const [user, setUser] = useState({ name: 'Алексей', age: 25 });
  
  return (
    <UserContext.Provider value={{ user, setUser }}>
      {children}
    </UserContext.Provider>
  );
};

// 3. Используем контекст в компоненте
const UserProfile = () => {
  const { user, setUser } = useContext(UserContext);
  
  return (
    <div>
      <p>Имя: {user.name}</p>
      <button onClick={() => setUser({ ...user, name: 'Виктория' })}>
        Изменить имя
      </button>
    </div>
  );
};

// 4. Обертываем приложение провайдером
const App = () => (
  <UserProvider>
    <UserProfile />
  </UserProvider>
);

4. Callback функции (потомок -> родитель)

// Родитель
const Parent = () => {
  const [value, setValue] = useState('');
  
  const handleChildClick = (data) => {
    console.log('Данные от ребенка:', data);
    setValue(data);
  };
  
  return (
    <div>
      <p>Значение: {value}</p>
      <Child onSendData={handleChildClick} />
    </div>
  );
};

// Ребенок
const Child = ({ onSendData }) => (
  <button onClick={() => onSendData('Привет из ребенка')}>
    Отправить данные
  </button>
);

5. State management (Zustand, Redux, Recoil)

// Пример с Zustand (простой и популярный)
import { create } from 'zustand';

const useUserStore = create((set) => ({
  user: { name: 'Алексей' },
  updateUser: (newUser) => set({ user: newUser })
}));

// Компонент 1
const Component1 = () => {
  const user = useUserStore((state) => state.user);
  return <div>Пользователь: {user.name}</div>;
};

// Компонент 2
const Component2 = () => {
  const updateUser = useUserStore((state) => state.updateUser);
  
  return (
    <button onClick={() => updateUser({ name: 'Виктория' })}>
      Обновить
    </button>
  );
};

6. Рефы (для доступа к DOM)

import { useRef } from 'react';

const Parent = () => {
  const inputRef = useRef(null);
  
  const handleFocus = () => {
    inputRef.current.focus();
  };
  
  return (
    <div>
      <Child ref={inputRef} />
      <button onClick={handleFocus}>Фокус на поле</button>
    </div>
  );
};

const Child = React.forwardRef((props, ref) => (
  <input ref={ref} placeholder="Введите текст" />
));

7. URL параметры и query string

import { useNavigate, useSearchParams } from 'react-router-dom';

// Передача через URL
const Component1 = () => {
  const navigate = useNavigate();
  
  const handleClick = () => {
    navigate('/profile?id=123&name=alex');
  };
  
  return <button onClick={handleClick}>Перейти</button>;
};

// Получение из URL
const Component2 = () => {
  const [searchParams] = useSearchParams();
  const id = searchParams.get('id');
  const name = searchParams.get('name');
  
  return <div>ID: {id}, Имя: {name}</div>;
};

8. Событие обновления (Event Bus)

// Простой event bus
class EventBus {
  constructor() {
    this.events = {};
  }
  
  on(event, callback) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(callback);
  }
  
  emit(event, data) {
    if (this.events[event]) {
      this.events[event].forEach((callback) => callback(data));
    }
  }
}

const bus = new EventBus();

// Компонент 1 (слушатель)
const ListenerComponent = () => {
  const [data, setData] = useState(null);
  
  useEffect(() => {
    bus.on('update', setData);
    return () => bus.off('update', setData);
  }, []);
  
  return <div>Данные: {data}</div>;
};

// Компонент 2 (отправитель)
const EmitterComponent = () => {
  const handleClick = () => {
    bus.emit('update', 'Новые данные');
  };
  
  return <button onClick={handleClick}>Отправить</button>;
};

Сравнение методов

МетодПлюсыМинусыКогда использовать
PropsПростой, явный поток данныхProps drilling при глубокой иерархииРодитель -> потомок, соседи через родителя
ContextИзбегает props drillingМожет вызвать лишние ре-рендерыГлобальные данные (тема, язык, юзер)
CallbackОбратная связьНемного запутанноПотомок -> родитель
State managerМасштабируемостьБольше кодаСложное состояние, много компонентов
URL paramsСохраняется в историиНебезопасно для конфиденциальных данныхФильтры, поиск, навигация

Рекомендации

  1. Для близких компонентов - используй props
  2. Для отдаленных компонентов - Context API
  3. Для сложного состояния - Zustand, Redux или Recoil
  4. Для фильтров и поиска - URL параметры
  5. Избегай props drilling - лучше используй Context
  6. Не переусложняй - KISS принцип
Как можно передавать данные между компонентами? | PrepBro