Отредактировано, чтобы добавить решение внизу
У меня есть проект, созданный с помощью 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
};
Каждый компонент получает реквизит как объект. В компоненте 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>>; Теперь он работает в моем приложении. Я ценю обратную связь.