我目前正在学习react 与它的文档,我给自己一个挑战,并想创建一个小聊天应用程序.我了解一些基本情况,我对各州也有意见.

在我的代码中,有一个Contact对象,它保存我的联系人的信息.我使用一个州来包含它,并创建了三个按钮,每个人的名字都在其中.对于按钮,我使用了一个带有两个props HandleButtonClick和Contact的组件.

const contacts = [
    {id: 0, name: 'Taylor', email: 'taylor@mail.com'},
    {id: 1, name: 'Alice', email: 'alice@mail.com'},
    {id: 2, name: 'Bob', email: 'bob@mail.com'},
  ];

const [contactList, setContactList] = useState(contacts);

<ContactList handleButtonClick={handleButtonClick} contacts={contactList} />

在组件内部:

export default function ContactList({ handleButtonClick, contacts }) {
  return (
    <div className="contact-buttons">
      {contacts.map((contact) => {
        return (
          <button
            key={contact.id}
            className="personName"
            onClick={handleButtonClick}
            value={contact.id}
          >
            {contact.name}
          </button>
        );
      })}
    </div>
  );
}

我想要做的事情是,当handleButtonClick执行时,它需要使用Person的id更新一个状态,并使用该id查找具有ContactList.find的正确的Person.


  const [selectedId, setSelectedId] = useState(0);
  const contact = contactList.find((c) => c.id === selectedId);

  function handleButtonClick(e){
    e.preventDefault()
    setSelectedId(e.target.value);
  }

问题是,对于第一人称联系,正确开始,但它永远不会更新.如果我没有弄错,当我设置选定的ID时,它应该会触发重新渲染并设置联系人.我错过了什么?谢谢你!!

推荐答案

当您更新selectedId状态时,您正在更改存储在selectedId状态中的内容的类型.最初,它是一个数字类型,它与contacts个对象中id个属性的类型一致.这就是为什么当你最初拨打.find()时,它可以正确地找到contact.然而,当您将您的状态更新为e.target.value时,您正在将您的id的string版本设置为该状态(这是因为.value property returns a string).当您在.find()方法中使用strict equality比较(===)时,您会发现更新后的selectedId与任何对象都不匹配,因为类型不同(您现在将对象中的数字ID与字符串状态ID进行比较).

您有几个选项可以解决这个问题.第一种是使用loose equality比较(==),而不是严格比较===,它不在乎类型是否不同:

const contact = contactList.find((c) => c.id == selectedId);

在某些情况下,==的行为可能会有点出人意料,所以通常情况下,最好还是坚持使用===.相反,我建议更改您的状态更新代码,将您的状态设置为数字而不是字符串.这里我用的是unary plus operator +,但你也可以用Number()来达到同样的效果:

setSelectedId(+e.target.value); // or `Number(e.target.value)`

或者,您可以丢弃按钮上的valueprops ,而是将选定的联系人传递到函数调用中,如下所示,这样您就不必在每次渲染时或在选定的ID更改时迭代contacts:

<button
  key={contact.id}
  className="personName"
  onClick={() => handleButtonClick(contact)}
>

然后,您的处理程序和状态将设置并保留一个联系人对象(如果可能):

const [selectedContact, setSelectedContact] = useState(() => contacts[0]);

function handleButtonClick(contact){
  e.preventDefault();
  setSelectedContact(contact);
}

Javascript相关问答推荐

如何在NightWatch.js测试中允许浏览器权限?

为什么getRecord()会因为与_logger相关的错误而失败?(使用Hedera SDK)

是什么原因导致此Angular 16电影应用程序中因类型错误而不存在属性?

如何用显示网格平滑地将元素从一个地方移动到另一个地方?

点击按钮一次有文本出现和褪色,而不是点击两次?(html,CSS,JavaScript)

Angular 17—每当一个布尔变量变为真时触发循环轮询,只要它保持为真

使用Java脚本导入gltf场景并创建边界框

在HTML语言中调用外部JavaScript文件中的函数

400 bad request error posting through node-fetch

查询参数中的JAVASCRIPT/REACT中的括号

在FAQ Accodion应用程序中使用React useState时出现问题

如何防止ionic 输入中的特殊字符.?

从逗号和破折号分隔的给定字符串中查找所有有效的星期几

Phaser3 preFX addGlow不支持zoom

如何使用画布在另一个内部绘制一个较小但相同的形状,同时保持恒定的边界厚度?

如何修复使用axios运行TSC index.ts时出现的错误?

Django导入问题,无法导入我的应用程序,但我已在设置中安装了它

ComponentWillReceiveProps仍在React 18.2.0中工作

更新文本区域行号

如何在Firebase中读取对象的特定字段?