Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 反应按钮单击事件更新状态值,但不反映在按钮文本上_Javascript_Reactjs_React Hooks - Fatal编程技术网

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;