仍然学习React的一些技巧。
我有以下代码在其中呈现按钮列表:
import React, { useState, useEffect } from 'react';
const MyComponent = (props) => {
const [buttonList, setButtonList] = useState([]);
useEffect(() => { getButtonList()}, [])
const getButtonList = () => {
let data = [
{id: 1, name: 'One', selected: false },
{id: 2, name: 'Two', selected: false },
{id: 3, name: 'Three', selected: false }
]
setButtonList(data)
}
const ButtonItem = ({ item }) => {
const btnClick = (event) => {
const id = event.target.value
buttonList.forEach((el) => {
el.isSelected = (el.id == id) ? true : false
})
setButtonList(buttonList)
console.log('buttonList', buttonList)
}
return (
<button type="button"
className={ "btn mx-2 " + (item.isSelected ? 'btn-primary' : 'btn-outline-primary') }
onClick={btnClick} value={item.id}>
{item.name + ' ' + item.isSelected}
</button>
)
}
return (
<div className="container-fluid">
<div className="card mb-3 rounded-lg">
<div className="card-body">
{
buttonList.map(item => (
<ButtonItem key={item.id} item={item} />
))
}
</div>
</div>
</div>
)
}
export default MyComponent;
因此按钮呈现:
[ One false ] [ Two false ] [ Three false ]
当我单击任何按钮时,我可以在Chrome React Tools上看到该按钮的isSelected
的值变为true
。我还可以确认在状态的开发工具中(在挂钩下)单击的按钮的特定数组项,值为true
。
如果我单击按钮One,则单击的按钮的文本不会显示[ One true ]
。我在这里想念什么?
P.S。请注意,我也想更改按钮的类,但是我认为,如果我知道在整个组件中都知道按钮isSelected
的值,那么该部分将得到解决。
代码演示: https://codesandbox.io/s/laughing-keller-o5mds?file=/src/App.js:666-735
答案 0 :(得分:3)
问题:您要对状态对象进行突变,而不是返回新的状态引用。您之前还使用===
将字符串id
与数字id
进行比较,该数字对于所有比较均返回false。
解决方案::使用功能性更新和array.map通过返回新数组来更新状态。
const ButtonItem = ({ item }) => {
const btnClick = event => {
const id = event.target.value;
setButtonList(buttons =>
buttons.map(button => ({
...button,
isSelected: button.id == id
}))
);
};
...
};
建议:剔除btnClick
处理程序,只需定义一次即可。咖喱id
的{{1}}属性,以便您可以使用item
。
===
更新点击处理程序的附件以传递商品ID
const btnClick = id => event => {
setButtonList(buttons =>
buttons.map(button => ({
...button,
isSelected: button.id === id
}))
);
};
答案 1 :(得分:0)
在btnClick
处理程序中,您正在改变状态,应该创建一个新值并分配给它:
import React from "react";
import "./styles.css";
import { useState, useEffect } from "react";
const ButtonItem = ({ item, onClick }) => {
return (
<button
type="button"
className={
"btn mx-2 " + (item.isSelected ? "btn-primary" : "btn-outline-primary")
}
onClick={() => onClick(item.id)}
value={item.id}
>
{item.name + " " + item.isSelected}
</button>
);
};
const MyComponent = props => {
const [buttonList, setButtonList] = useState([]);
useEffect(() => {
getButtonList();
}, []);
const getButtonList = () => {
let data = [
{ id: 1, name: "One", isSelected: false },
{ id: 2, name: "Two", isSelected: false },
{ id: 3, name: "Three", isSelected: false }
];
setButtonList(data);
};
const btnClick = id => {
const updatedList = buttonList.map(el => ({
...el,
isSelected: el.id === id
}));
setButtonList(updatedList);
console.log("buttonList", updatedList);
};
return (
<div className="container-fluid">
<div className="card mb-3 rounded-lg">
<div className="card-body">
{buttonList.map(item => (
<ButtonItem key={item.id} item={item} onClick={btnClick} />
))}
</div>
</div>
</div>
);
};
export default MyComponent;