我一直在尝试增加列表中项目的数量,当单击与该项目对应的插入符号按钮时。但是作为一个反应新手,我已经经历了很多我学到的方法,例如使用钩子、数组方法,但我想要的输出仍然没有返回。
注意:我想要的输出是让用户能够单击插入符号(向上或向下(,这将分别触发项目数量的增加或减少。
在这场斗争中,我得到了一个提示,在这里寻求帮助(所以这是我第一次(。我希望得到我的答案...谢谢。
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
的方式做更多的事情,破坏您的组件会让它变得更好
首先创建一个项目组件
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>
);
};
然后映射项目并呈现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
来更新无法按预期工作的项目计数,这种破坏事物的方式,每个项目都有自己的状态,更新后将仅反映在该项目上
你的问题是你使用的是单个count
,你可以使用一个counts
数组,并通过index
将其与sides
数组映射,
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;