反应按钮单击事件更新状态值,但未反映在按钮文本上

时间:2020-04-23 06:59:24

标签: javascript reactjs react-hooks

仍然学习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

2 个答案:

答案 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
      }))
    );
  };

  ...
};

Edit elastic-ardinghelli-3dw61

建议:剔除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;