Как добавить класс элементу в зависимости от состояние кнопок (React)?
Есть функциональный компонент Calories. В нем 3 компонента. 1й - Btns - рендерит 2 кнопки (одна из них активна), 2й и 3й компоненты - рендерит таблицы.
Как добавлять класс show во 2й и 3й компоненты при смене состояния кнопок?
export default function Calories() {
return ( <
section id = 'сalories' >
<Btns items = {['male', 'female']}/>
<table id = 'table-men' className = { ... ? 'bw show' : 'bw' } >
...
</table>
<table id = 'table-women' className = { ... ? 'bw show' : 'bw' } >
...
</table>
</section>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Ответы (1 шт):
Автор решения: Denis Merioara
→ Ссылка
Буду рад обратной связи если удалось помочь и/или оценке представленного ответа
import React, { useState, useCallback, memo } from "react";
/* #region Btns Component */
interface BtnsProps {
items?: string[];
onClick: (
buttonType: string
) => (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
}
const Btns = memo((props: BtnsProps) => {
const { items, onClick } = props;
if (!items) return null;
return (
<>
{items.map((id) => (
<button key={id} onClick={onClick(id)}>
{id}
</button>
))}
</>
);
});
/* #endregion */
/* #region Table Component */
interface TableProps {
id: string;
isActive?: boolean;
}
/** Компонент отрисовки данных */
const Table = memo((props: TableProps) => {
const { id, isActive } = props;
return (
<table id={`table-${id}`} className={isActive ? "bw show" : "bw"}>
<tbody>
<tr>
<td>
... {id}: {isActive ? "bw show" : "bw"}
</td>
</tr>
</tbody>
</table>
);
});
/* #endregion */
/* #region Calories Component */
interface CaloriesProps {
/** Словарь кнопок */
buttons?: string[];
}
/** Хук хранения данных и обработки событий */
const useDataCalories = (props: CaloriesProps) => {
const { buttons } = props;
/** Состояние компонента */
const [activeButton, setActiveButton] = useState(buttons?.[0]);
/**
* Обработчик события click по кнопке
* @remark useCallback нужен потому что обработчик прокидывается в дочерний компонент
*/
const handleClick = useCallback(
(buttonType: string) =>
(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
event.preventDefault();
if (buttonType === activeButton) return;
setActiveButton(buttonType);
},
[activeButton]
);
return { buttons, activeButton, handleClick };
};
function Calories(props: CaloriesProps) {
const { buttons, activeButton, handleClick } = useDataCalories(props);
return (
<section id="сalories">
<Btns items={buttons} onClick={handleClick} />
{buttons?.map((id) => (
<Table key={id} id={id} isActive={id === activeButton} />
))}
</section>
);
}
Calories.defaultProps = {
buttons: ["male", "female"],
};
/* #endregion */
export default Calories;