为了账号安全,请及时绑定邮箱和手机立即绑定

为 React Bootstrap ListGroup 实现类型的问题

为 React Bootstrap ListGroup 实现类型的问题

HUX布斯 2023-05-11 16:44:08
我正在这个 React App 中实现 typescript。我正在使用 react-bootstrap(已经安装了类型)。我有一个列表组,其中包含如下操作项。要获取我拥有的每个项目的点击事件的类型:((event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void) 不确定为什么它会建议这种类型,因为当我检查 DOM 时,我看到了按钮。不管怎样,下面是列表组的代码。<ListGroup id="riskQuestion-1" >   <ListGroup.Item action onClick={(event:((event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void) | undefined) => handleInput(setRiskAnswer1, 5, event)} >I was great!</ListGroup.Item>   <ListGroup.Item action onClick={(event:((event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void) | undefined) => handleInput(setRiskAnswer2, 3, event)}>I did good but can be better</ListGroup.Item></ListGroup>    那么我的 handleInput 函数是: const [riskAnswer1, setRiskAnswer1] = useState<number | null>(null); const [riskAnswer2, setRiskAnswer2] = useState<number | null>(null); interface InputParams {    answerHandler:React.Dispatch<React.SetStateAction<number | null>>,    value: number,    event: ((event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void) | undefined  }  function handleInput({answerHandler, value, event}:InputParams) {    event.preventDefault();    const parentEl = event.target.parentNode;    const  parentId = parentEl.getAttribute("id");    if (parentId) {      const el = document.getElementById(parentId);      if (el) {        for (let i=0; i < el.children.length; i++) {          if (el.children[i].classList.contains('selected')) {            el.children[i].classList.remove('selected');          }        }      }    }        event.target.classList.add("selected");    answerHandler(value);  }我在这段代码中确实有一些 event.target 问题,但这可能与手头的主要问题有关,也可能无关。现在的主要问题是打字稿仍然显示错误onClick。当我将鼠标悬停在下方时,就是我所看到的。所以两个问题:1-我需要改变什么2- 起初我将所有类型的参数内联在括号内,但我将它们移到interface InputParams现在有了这个更改,我在列表组项目上调用 handleInput,我看到了这个错误:Expected 1 arguments, but got 3.ts(2554)所以似乎 function handleInput({answerHandler, value, event}:InputParams) {不是正确的方法在这里实现类型?不要担心上面的所有错误都是在我将所有参数类型都内联时生成的。所以这只是我想问的额外问题。感谢任何指导。谢谢你!
查看完整描述

1 回答

?
蛊毒传说

TA贡献1895条经验 获得超3个赞

问题是onClick处理程序的当前类型签名基本上声明参数event本身是一个函数。要纠正这个问题,您只想使用事件本身的类型:


<ListGroup id="riskQuestion-1">

  <ListGroup.Item

    action

    onClick={(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) =>

      handleInput(setRiskAnswer1, 5, event)

    }

  >

    I was great!

  </ListGroup.Item>

  <ListGroup.Item

    action

    onClick={(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) =>

      handleInput(setRiskAnswer2, 3, event)

    }

  >

    I did good but can be better

  </ListGroup.Item>

</ListGroup>

事实上,由于您不想访问仅在元素上找到的属性<a>,您可以让类型默认为最广泛的类型:Element,这样您就可以省略泛型。它在这里的原因HTMLAnchorElement是ListGroup.Item带有一个action呈现链接 - 使用浏览器的开发人员工具的 DOM 检查器查看生成的 HTML。你会看到<a>那里。虽然它可以是任何东西,实际上你可以通过asprop指定它。


<ListGroup id="riskQuestion-1">

  <ListGroup.Item

    action

    onClick={(event: React.MouseEvent) =>

      handleInput(setRiskAnswer1, 5, event)

    }

  >

    I was great!

  </ListGroup.Item>

  <ListGroup.Item

    action

    onClick={(event: React.MouseEvent) =>

      handleInput(setRiskAnswer2, 3, event)

    }

  >

    I did good but can be better

  </ListGroup.Item>

</ListGroup>

要解决你的第二个问题,function handleInput({answerHandler, value, event}:InputParams)是一个接受一个参数的函数,该参数是具有这些属性的对象。但是,您handleInput使用三个单独的参数进行调用,因此它应该是:


function handleInput(

  answerHandler: React.Dispatch<React.SetStateAction<number | null>>,

  value: number,

  event: React.MouseEvent

)

由于您不在此处使用功能更新,因此您可以摆脱以下问题:


function handleInput(

  answerHandler: (answer: number | null) => void,

  value: number,

  event: React.MouseEvent

)

解决这些问题后,更多问题出现在handleInput. 第一个是 thatevent.target可能不是一个元素,因此它的类型没有.parentNode. 在这种情况下,最好使用.currentTarget. 另请参阅javascript 中的 currentTarget 属性和 target 属性之间的确切区别是什么。


修改后的函数为:


function handleInput(

  answerHandler: (answer: number | null) => void,

  value: number,

  event: React.MouseEvent

) {

  event.preventDefault();


  const parentEl = event.currentTarget.parentNode;

  const parentId = parentEl.getAttribute("id");

  if (parentId) {

    const el = document.getElementById(parentId);

    if (el) {

      for (let i = 0; i < el.children.length; i++) {

        if (el.children[i].classList.contains("selected")) {

          el.children[i].classList.remove("selected");

        }

      }

    }

  }


  event.currentTarget.classList.add("selected");

  answerHandler(value);

}

但是,唉,又出现了一个错误。这次是因为parentNode是类型Node。实际上有很多节点类型,“元素”只是其中之一!但显然,您实际上对父元素感兴趣,因此通过更改parentNode为parentElement,函数编译:


function handleInput(

  answerHandler: (answer: number | null) => void,

  value: number,

  event: React.MouseEvent

) {

  event.preventDefault();


  const parentEl = event.currentTarget.parentElement;

  const parentId = parentEl.getAttribute("id");

  if (parentId) {

    const el = document.getElementById(parentId);

    if (el) {

      for (let i = 0; i < el.children.length; i++) {

        if (el.children[i].classList.contains("selected")) {

          el.children[i].classList.remove("selected");

        }

      }

    }

  }


  event.currentTarget.classList.add("selected");

  answerHandler(value);

}

作为结束语,我只是一般性地说,这种直接的 DOM 操作在 React 世界中非常粗略,并且在大多数情况下可以而且应该用 React 来实现。


查看完整回答
反对 回复 2023-05-11
  • 1 回答
  • 0 关注
  • 127 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信