Javascript 反应按钮单击事件更新状态值,但不反映在按钮文本上
仍在学习一些反应技巧 我使用以下代码呈现按钮列表:Javascript 反应按钮单击事件更新状态值,但不反映在按钮文本上,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,仍在学习一些反应技巧 我使用以下代码呈现按钮列表: import React, { useState, useEffect } from 'react'; const MyComponent = (props) => { const [buttonList, setButtonList] = useState([]); useEffect(() => { getButtonList()}, []) const getButtonList = () => {
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;
当我点击任何按钮时,我可以在Chrome React Tools上看到该按钮的isSelected
值变为true
。我还可以确认在dev tools for State(hooks下)中单击的按钮的特定数组项的值为true
单击按钮的文本不显示[One true]
如果我单击了按钮1。我错过了什么
请注意,我还想更改按钮的类别,但我认为,如果我获得整个组件中已知的按钮isSelected
值,该部分将得到解决
代码演示:
问题:您正在修改状态对象,而不是返回新的状态引用。您以前还使用
==
将字符串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
}))
);
};
...
};
建议:排除b单击处理程序,它只需要定义一次。使用项的id
属性
,以便可以使用=
const btnClick = id => event => {
setButtonList(buttons =>
buttons.map(button => ({
...button,
isSelected: button.id === id
}))
);
};
更新click处理程序的附加以传递项目id
const ButtonItem = ({ item }) => {
return (
<button
type="button"
className={
"btn mx-2 " +
(item.isSelected ? "btn-primary" : "btn-outline-primary")
}
onClick={btnClick(item.id)} // <-- pass item.id to handler
value={item.id}
>
{item.name + " " + item.isSelected}
</button>
);
};
const ButtonItem=({item})=>{
返回(
在您的b单击处理程序中,您正在改变您的状态,您应该创建一个新值并将其赋值:
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;
从“React”导入React;
导入“/styles.css”;
从“react”导入{useState,useffect};
const ButtonItem=({item,onClick})=>{
返回(
onClick(item.id)}
值={item.id}
>
{item.name+“”+item.isSelected}
);
};
常量MyComponent=props=>{
const[buttonList,setButtonList]=useState([]);
useffect(()=>{
getButtonList();
}, []);
常量getButtonList=()=>{
让数据=[
{id:1,名称:“一”,isSelected:false},
{id:2,名称:“2”,isSelected:false},
{id:3,名字:“三”,isSelected:false}
];
设置按钮列表(数据);
};
常量btnClick=id=>{
const updatedList=buttonList.map(el=>({
…呃,
isSelected:el.id==id
}));
setButtonList(更新列表);
日志(“按钮列表”,更新列表);
};
返回(
{buttonList.map(项=>(
))}
);
};
导出默认MyComponent;
我可以看到您提供的示例CodeSandbox工作正常,但我想了解为什么我直接将值设置到数组项的部分不工作?另外,我的id比较使用的是=
,因为我知道我使用的代码类型不同,但我正在更改代码以使用id的字符串GUID。@Chett它基本上不起作用,因为您已将相同的数组引用保存回状态。React使用浅层引用相等性检查来确定组件何时应重新渲染。我最初还尝试排除btnClick函数(如您在示例中所设置的)但我遇到了一些奇怪的错误,不允许我传递参数。因此,我必须将其更改为代码示例中的值。不过我有一个add'l问题。这一行constbtnclick=id=>event=>
在我看来很奇怪。通常我编写的函数类似于constfn=(param)=>{}
。我在哪里学这些东西?@Chett这是一个叫做的概念。const-fn=(a,b)=>{}
你附加为onClick={b=>fn(a,b)}
相当于const-fn=>a=>b=>{/code>你附加为onClick={b=>fn(a)(b)}
或者更直接地附加为onClick={fn(a)}
。它允许您将a
存储在回调实例的附件中。f(a)=b=>{}
感谢您的回答。我尝试了您的解决方案,它也很有效。虽然我必须标记第一个得到的答案(Drew Reese)并帮助解决问题+解释一些术语。我也非常感谢您的时间。
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;