Передача данных от дочернего к родительскому компоненту в React

Отредактировано, чтобы добавить решение внизу

У меня есть проект, созданный с помощью React и Typescript.

Существует родительский компонент (Home), который отображает дочерний компонент в зависимости от значения переменной состояния «currentDemo». Цель состоит в том, чтобы иметь компонент навигации, который будет отображать любой элемент, на который был нажат щелчок. Каждый элемент навигации имеет связанный идентификатор, который относится к отображаемому компоненту. То есть элемент навигации «a» должен отображать компонент «a», элемент навигации «b» должен отображать компонент «b» и т. д. Вот фрагмент кода.

Home.tsx (родительский):

import React, { useState } from 'react';
import { Intro } from 'app/components/intro/Intro';
import { SidebarNav } from 'app/components/sidebarNav/SidebarNav';
import { ComponentA } from 'app/components/ComponentA/ComponentA';
import { ComponentB } from 'app/components/ComponentB/ComponentB';

export function Home() {
  //use state to track which demo is currently displayed ('intro' is default)
  const [currentDemo, setCurrentDemo] = useState('intro');

  return (
    <>
      <Header />
      <div className = "home">
        <SidebarNav setCurrentDemo = {setCurrentDemo} />
        {currentDemo === 'intro' && <Intro />}
        {currentDemo === 'ComponentA' && <ComponentA/>}
        {currentDemo === 'ComponentB' && <ComponentB/>}
      </div>
    </>
  );
}


SidebarNav.tsx (дочерний):

import React, { useState } from 'react';

const navData = [
  {
    title: 'Introduction',
    id: 'intro'
  },
  {
    title: 'Component A',
    id: 'ComponentA'
  },
  {
    title: 'Component B',
    id: 'ComponentB'
  }
];

export function SidebarNav(setCurrentDemo: any) {

  //GOAL: PASS ID OF SELECTED NAV ITEM TO PARENT COMPONENT AND SET VALUE OF 'CURRENTDEMO' TO THAT ID
  const handleCurrentClick = (id: any) => {
    if (id === 'intro') {
      setCurrentDemo('ComponentA');
    } else if (id === 'ComponentA') {
      setCurrentDemo('ComponentB');
    } else if (id === 'ComponentB') {
      setCurrentDemo('intro');
    }
  };

  return (
    <div className = "sidebarNav">
      <div className = "sidebarNav__container">
        {navData?.map((item, index) => (
          <div key = {index}>
            <button
              onClick = {() => {
                handleCurrentClick(item.id);
              }}
              id = {item.id}
            >
              {item.title}
            </button>
          </div>
        ))}
      </div>
    </div>
  );
}

Конкретная реализация компонентов A и B не имеет значения для этого сценария. Я проверил, вручную установив значение «currentDemo», и отобразится правильная демонстрация. Я также подтвердил, что идентификаторы для каждого элемента навигации правильно отображаются через console.info(item.id).

Как я могу передать значение идентификатора из SidebarNav в Home, установив значение currentDemo для идентификатора элемента навигации, который был нажат? Я чувствую, что я близок, но это не совсем так.

При нажатии на любой из элементов навигации появляется ошибка консоли, указывающая, что setCurrentDemo не является функцией. Это имеет смысл, потому что это установщик для состояния, но как я могу указать, что мы хотим фактически установить для currentDemo значение идентификатора элемента?

Вот решение, которое сработало для этого приложения. Внесенные изменения находятся в компоненте навигации. Добавлен интерфейс в навигацию и настроен как таковой:

interface SidebarNavProps {
  setCurrentDemo: React.Dispatch<SetStateAction<string>>;
}

export function SidebarNav(props: SidebarNavProps) {
  const { setCurrentDemo } = props;

...rest of function remains the same 

};


Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Каждый компонент получает реквизит как объект. В компоненте SidebarNav реквизит будет выглядеть так { setCurrentDemo } :any, а не setCurrentDemo:any.

Вот интерфейс для компонента SidebarNav

import { SetStateAction } from "react";

interface SidebarNavProps {
  setCurrentDemo: SetStateAction<string>
}

И ваш компонент SidebarNav будет выглядеть так:

export function SidebarNav(props: SidebarNavProps) {
  const { setCurrentDemo } = props;

  //GOAL: PASS ID OF SELECTED NAV ITEM TO PARENT COMPONENT AND SET VALUE OF 'CURRENTDEMO' TO THAT ID
  const handleCurrentClick = (id: any) => {
    if (id === 'intro') {
      setCurrentDemo('ComponentA');
    } else if (id === 'ComponentA') {
      setCurrentDemo('ComponentB');
    } else if (id === 'ComponentB') {
      setCurrentDemo('intro');
    }
  };

  return (
    <div className = "sidebarNav">
      <div className = "sidebarNav__container">
        {navData?.map((item, index) => (
          <div key = {index}>
            <button
              onClick = {() => {
                handleCurrentClick(item.id);
              }}
              id = {item.id}
            >
              {item.title}
            </button>
          </div>
        ))}
      </div>
    </div>
  );
}

Это исправит эту ошибку, и вы сможете сохранить идентификатор в состоянии, используя setCurrentDemo.

Спасибо! Мне пришлось внести небольшое изменение в интерфейс, в основном setCurrentDemo: React.Dispatch<SetStateAction<string>>; Теперь он работает в моем приложении. Я ценю обратную связь.

dcmswim 28.11.2022 17:38

вы можете определить состояние в родительском и установить это состояние в дочернем компоненте для передачи данных от дочернего к родительскому

Я понимаю слова в вашем комментарии, но пример будет иметь большое значение, чтобы показать, как именно это будет работать!

dcmswim 28.11.2022 17:36

Другие вопросы по теме