React изменение состояния для каждого элемента по своему
Делал приложение по бронированию мест, свободные места отмечены зеленым, занятые красным. "Места" у меня в массиве "placeDB" с помощью map вывожу. При клике на этот элемент появляется модальное окно, где есть кнопка "Бронь". По клику "Бронь" окрашиваются все блоки, а надо что бы каждый блок окрашивался только по своему по клику.
Фрагмент
import {useState} from "react";
import Modal from "../modal/modal";
import placeDB from "../placeDB/place";
function OfficeMap(){
const [modalActive, setModalActive ] = useState(false);
const [colorPlace, setColorPlace] = useState(false);
return(
<>
<div className="freelance_office">
{placeDB.map((pop)=>{
return(
<div style={{background: colorPlace ? 'red' : 'green'}} className={pop.className} onClick={()=>setModalActive(true)}>
<p>Описание {pop.description}</p>
</div>
)
})}
<Modal changeColor={setColorPlace} active={modalActive} setActive={setModalActive}/>
</div>
</>
)
}
export default OfficeMap;
в placeDB содержится
const placeDB = [
{id: 1,
description: "Место 1",
className: "open_description_place_1"
},
{
id: 2,
description: "Место 2",
className: "open_description_place_2"
},
{
id: 3,
description: "Место 3",
className: "open_description_place_3"
},
{
id: 4,
description: "Место 4",
className: "open_description_place_4"
},
{ id: 5,
description: "Место 5",
className: "open_description_place_5"
},
]
export default placeDB;
модальное окно
import React from "react"
import "./modal.css"
const Modal = ({active, setActive, changeColor}) =>{
return(
<div className={active ? "modal active" : "modal"} onClick={()=>setActive(false)}>
<div className={active ? "modal__content active" : "modal"} onClick={e => e.stopPropagation()}>
<button className="modal_btn" onClick={() => changeColor(c => !c)}>Бронь!</button>
</div>
</div>
)
}
export default Modal;
Ответы (1 шт):
Я бы добавли в структуру данных свойство, отвечающее за бронь места isBronned: false
Далее при нажатии на элемент сохраняем элемент в состоянии и передаем его в компонент Modal вместе с фукнцией по применению бронирования bronned.
При нажатии на кнопку бронь, передается id места и его статус (забронировано/не забронировано). Сохраняем эти значения.
Во время рендера списка смотрим на isBronned и в зависимости от этого закрашиваем нужным цветом.
const placeDB = [
{
id: 1,
description: "Место 1",
className: "open_description_place_1",
isBronned: false
},
{
id: 2,
description: "Место 2",
className: "open_description_place_2",
isBronned: false
},
{
id: 3,
description: "Место 3",
className: "open_description_place_3",
isBronned: false
},
{
id: 4,
description: "Место 4",
className: "open_description_place_4",
isBronned: false
},
{
id: 5,
description: "Место 5",
className: "open_description_place_5",
isBronned: false
}
];
const Modal = ({ active, setActive, changeColor, place }) => {
return (
<div
className={active ? "modal active" : "modal"}
onClick={() => setActive(false)}
>
<div
className={active ? "modal__content active" : "modal"}
onClick={(e) => e.stopPropagation()}
>
{place && (
<button
className="modal_btn"
onClick={() => {
changeColor(place.id, !place.isBronned);
}}
>
{place?.isBronned
? `Снять бронь ${place?.description}`
: `Забронировать ${place?.description}`}
</button>
)}
</div>
</div>
);
};
function OfficeMap() {
const [modalActive, setModalActive] = useState(false);
const [places, setPlaces] = useState(placeDB);
const [selPlace, setSelPlace] = useState(null);
const bronned = (id, bron) => {
setPlaces(
places.map((it) => {
if (it.id === id) it.isBronned = bron;
return it;
})
);
};
return (
<>
<div className="freelance_office">
{places.map((pop) => {
return (
<div
style={{ background: pop.isBronned ? "red" : "green" }}
className={pop.className}
onClick={() => {
setModalActive(true);
setSelPlace(pop);
}}
>
<p>Описание {pop.description}</p>
</div>
);
})}
<Modal
changeColor={bronned}
place={selPlace}
active={modalActive}
setActive={setModalActive}
/>
</div>
</>
);
}