So here's my problem, i map some data i receive from the back, it returns a group of div, i would like to be able to click a div, change his color background and use it in total price (they're options you can choose).
i tried to put a state "clicked" which set true on click, but the state is on all element ans not the only one i just clicked. After if my state is true, i change the background color and add it to the total price (calculated in the modal in details)
<p className="title-config">Configuration</p>
{data &&
data.additionalCharges.map((charges, index) => {
// console.log("charges.map", charges);
return (
<div
className={
clicked === true ? "clicked-config" : "unclicked-config"
}
key={index}
onClick={() => setClicked(true)}
>
<p>{charges.title}</p>
<p>{charges.description}</p>
<p>
{charges.price.amount} {location.state.price.currency}
</p>
</div>
);
})}
</div>
<div className="colonne2-config">
<div>
<span> Total {location.state.total}</span>
<span>{location.state.price.amount}</span>
</div>
<div>
<div onClick={() => setShowModal(true)}>Voir les details du prix</div>
<Modal
isOpen={showModal}
onRequestClose={() => setShowModal(false)}
style={{
overlay: {
backgroundColor: "lightgrey",
backgroundOpacity: "50%",
},
}}
>
<h1>Details du prix</h1>
<button onClick={() => setShowModal(false)}> X </button>
</Modal>
</div>
CodePudding user response:
Here is a working example to achieve the desired objective:
Code Snippet
const {useState} = React;
const SomeComponent = ({data, ...props}) => {
// the clicked is being used to achieve two goals
// 1. track which item is clicked (ie, selected)
// 2. update the total-price by adding / subtracting the clicked item's price
// NOTE: This is not a good approach to employ in general. Please avoid.
// Instead, use a separate variable to calculate the total-price.
const [clicked, setClicked] = useState({total: 0});
const getClass = idx => (`item ${clicked[idx] ? 'selected' : 'unselected'}`);
return (
<div>
<h4>List of Items</h4>
{
data && Array.isArray(data) && data.map(
({title, description, amount}, idx) => (
<div
key={idx}
onClick={() => setClicked(prev => ({
...prev,
total: (
prev[idx] ? prev.total - amount : prev.total amount
),
[idx]: !prev[idx]
}))}
class={getClass(idx)}
>
{title}   {description}   {amount}
</div>
)
)
}
<br/>
Total Price: {clicked.total}
</div>
);
};
const rawData = [
{title: 'Title 00', description: 'Description 00', amount: '100'},
{title: 'Title 01', description: 'Description 01', amount: '110'},
{title: 'Title 02', description: 'Description 02', amount: '120'},
{title: 'Title 03', description: 'Description 03', amount: '130'},
{title: 'Title 04', description: 'Description 04', amount: '140'},
{title: 'Title 05', description: 'Description 05', amount: '150'},
{title: 'Title 06', description: 'Description 06', amount: '160'}
];
ReactDOM.render(
<div>
<h2>DEMO</h2>
<SomeComponent data={rawData}/>
</div>,
document.getElementById('reactdiv')
);
.item {
border: 2px solid black;
margin-bottom: 10px;
padding: 2px 15px;
cursor: default;
width: fit-content;
}
.unselected { background-color: #EEEEFF; }
.selected { background-color: #6666AA; color: white}
<div id='reactdiv'/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
Explanation
- The
clicked
needs to be a data-structure that can track which of the items rendered are clicked (ie, selected) and which are not. - In this snippet, it is set as an object
- For simplicity of the demo, the same
clicked
object serves a secondary purpose of holding thetotal
price. - When user clicks on any item, it's background color changes (using
getClass
method) - And, the price of the item is added to or removed from
total
Overall - this is a fairly simple, straight-forward code snippet.
CodePudding user response:
As per my understanding of the question what you can do is, add another state called divIndex and change the condition to clicked && divIndex === index
or you can just remove the clicked state and only use the divIndex state also like divIndex === index.