[英]How can I add a click event on an individual Element in a mapped array in react
當單擊與項目相對應的插入符號按鈕時,我一直在嘗試增加列表中項目的數量。 但是作為一個反應新手,我經歷了很多我學到的方法,比如使用鈎子、數組方法,但仍然沒有返回我想要的 output。
注意:我想要的 output 是為了讓用戶能夠單擊插入符號(向上或向下),這將分別觸發項目數量的增加或減少。
在這場斗爭中,我得到了一個提示,想在這里尋求幫助(所以這是我的第一次)。 我希望得到我的答案...謝謝。
import React, {useState} from 'react';
import { category } from '../categories.json';
import {
Card,
CardBody,
CardTitle
} from 'reactstrap';
import { faCaretDown, faCaretUp } from '@fortawesome/free-solid-svg-icons'
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
const Sides = () => {
let [count, setCount] = useState(1)
function Increment(event) {
console.log(event.target);
let sides = category[0].sides.forEach(item => {
let targetId = event.target.dataset.id;
item.find((item)=> item.id !== targetId)
})
console.log(sides.id);
if(sides) {
setCount(count + 1);
}
}
const Decrement = () => {
console.log('Decreasing');
}
function renderNames() {
return(
<div>
<table>
<thead>
<tr>
<th>items</th>
<th>qty</th>
<th>price</th>
<th>check</th>
</tr>
</thead>
<tbody>
{category[0].sides.map(item => (
<tr key={item.id}>
<td>{item.name}</td>
<td style={{display: 'flex', alignItems: 'center'}}>
<div style={{display: 'grid'}}>
<div onClick={Increment} >
<FontAwesomeIcon icon={faCaretUp} data-id={item.id}/>
</div>
<div>
<FontAwesomeIcon icon={faCaretDown}/>
</div>
</div>
{count}
</td>
<td>{item.price}</td>
<td>
<input type="checkbox" name="" id=""/>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
return (
<>
<Card>
<CardTitle>
<h2>Sides list</h2>
</CardTitle>
<CardBody>
<div style={{display: 'flex', padding: '5px'}}>
{renderNames()}
</div>
</CardBody>
</Card>
</>
)
}
export default Sides;
首先你需要開始思考 React 的方式,所以不需要data-x
屬性,為了達到同樣的效果,你可以通過點擊事件傳遞項目 ID,比如
<div onClick={() => Increment(item.id)}>
但是讓我們以React
的方式做更多的事情,打破你的組件讓它變得更好
首先創建一個Item組件
export const Item = ({ item }) => {
const [count, setCount] = React.useState(0);
const { id, name, price } = item;
const Increment = () => {
setCount(count + 1);
};
return (
<tr>
<td>{name}</td>
<td style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ display: 'grid' }}>
<div onClick={Increment}>
<FontAwesomeIcon icon={faCaretUp} />
</div>
<div>
<FontAwesomeIcon icon={faCaretDown} />
</div>
</div>
{count}
</td>
<td>{price}</td>
<td>
<input type="checkbox" name="" id="" />
</td>
</tr>
);
};
然后 map 通過 items 渲染Item
組件
const Sides = () => {
function renderNames() {
return (
<div>
<table>
<thead>
<tr>
<th>items</th>
<th>qty</th>
<th>price</th>
<th>check</th>
</tr>
</thead>
<tbody>
{category[0].sides.map(item => (
<Item key={item.id} item={item} />
))}
</tbody>
</table>
</div>
);
}
return (
<Card>
<CardTitle>
<h2>Sides list</h2>
</CardTitle>
<CardBody>
<div style={{ display: 'flex', padding: '5px' }}>
{renderNames()}
</div>
</CardBody>
</Card>
);
};
您面臨的問題是您還使用一個state
來更新項目計數,這將無法按預期工作,這種破壞方式,每個項目都有自己的 state 並且更新時將僅反映該項目
您的問題是您使用的是單個count
,您可以使用counts
數組和 map 它與sides
數組按index
,
sides[0]
為counts[0]
, sides[1]
為counts[1]
...
嘗試這個:
import React, {useState} from 'react';
import { category } from '../categories.json';
import {
Card,
CardBody,
CardTitle
} from 'reactstrap';
import { faCaretDown, faCaretUp } from '@fortawesome/free-solid-svg-icons'
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
const Sides = () => {
let [counts, setCounts] = useState([])
const Increment = (index) => {
let newCounts = [...counts]
newCounts[index] += 1
setCounts(newCounts);
}
const Decrement = (index) => {
if (counts[index] > 0) {
let newCounts = [...counts]
newCounts[index] -= 1
setCounts(newCounts);
}
}
function renderNames() {
return(
<div>
<table>
<thead>
<tr>
<th>items</th>
<th>qty</th>
<th>price</th>
<th>check</th>
</tr>
</thead>
<tbody>
{category[0].sides.map((item, index) => (
<tr key={item.id}>
<td>{item.name}</td>
<td style={{display: 'flex', alignItems: 'center'}}>
<div style={{display: 'grid'}}>
<div onClick={() => Increment(index)} >
<FontAwesomeIcon icon={faCaretUp} data-id={item.id}/>
</div>
<div onClick={() => Decrement(index)}>
<FontAwesomeIcon icon={faCaretDown}/>
</div>
</div>
{counts[index]}
</td>
<td>{item.price}</td>
<td>
<input type="checkbox" name="" id=""/>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
return (
<>
<Card>
<CardTitle>
<h2>Sides list</h2>
</CardTitle>
<CardBody>
<div style={{display: 'flex', padding: '5px'}}>
{renderNames()}
</div>
</CardBody>
</Card>
</>
)
}
export default Sides;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.