为 React Bootstrap ListGroup 实现类型的问题

我正在这个 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) {不是正确的方法在这里实现类型?不要担心上面的所有错误都是在我将所有参数类型都内联时生成的。所以这只是我想问的额外问题。

感谢任何指导。谢谢你!


HUX布斯
浏览 178回答 1
1回答

蛊毒传说

问题是onClick处理程序的当前类型签名基本上声明参数event本身是一个函数。要纠正这个问题,您只想使用事件本身的类型:<ListGroup id="riskQuestion-1">&nbsp; <ListGroup.Item&nbsp; &nbsp; action&nbsp; &nbsp; onClick={(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) =>&nbsp; &nbsp; &nbsp; handleInput(setRiskAnswer1, 5, event)&nbsp; &nbsp; }&nbsp; >&nbsp; &nbsp; I was great!&nbsp; </ListGroup.Item>&nbsp; <ListGroup.Item&nbsp; &nbsp; action&nbsp; &nbsp; onClick={(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) =>&nbsp; &nbsp; &nbsp; handleInput(setRiskAnswer2, 3, event)&nbsp; &nbsp; }&nbsp; >&nbsp; &nbsp; I did good but can be better&nbsp; </ListGroup.Item></ListGroup>事实上,由于您不想访问仅在元素上找到的属性<a>,您可以让类型默认为最广泛的类型:Element,这样您就可以省略泛型。它在这里的原因HTMLAnchorElement是ListGroup.Item带有一个action呈现链接 - 使用浏览器的开发人员工具的 DOM 检查器查看生成的 HTML。你会看到<a>那里。虽然它可以是任何东西,实际上你可以通过asprop指定它。<ListGroup id="riskQuestion-1">&nbsp; <ListGroup.Item&nbsp; &nbsp; action&nbsp; &nbsp; onClick={(event: React.MouseEvent) =>&nbsp; &nbsp; &nbsp; handleInput(setRiskAnswer1, 5, event)&nbsp; &nbsp; }&nbsp; >&nbsp; &nbsp; I was great!&nbsp; </ListGroup.Item>&nbsp; <ListGroup.Item&nbsp; &nbsp; action&nbsp; &nbsp; onClick={(event: React.MouseEvent) =>&nbsp; &nbsp; &nbsp; handleInput(setRiskAnswer2, 3, event)&nbsp; &nbsp; }&nbsp; >&nbsp; &nbsp; I did good but can be better&nbsp; </ListGroup.Item></ListGroup>要解决你的第二个问题,function handleInput({answerHandler, value, event}:InputParams)是一个接受一个参数的函数,该参数是具有这些属性的对象。但是,您handleInput使用三个单独的参数进行调用,因此它应该是:function handleInput(&nbsp; answerHandler: React.Dispatch<React.SetStateAction<number | null>>,&nbsp; value: number,&nbsp; event: React.MouseEvent)由于您不在此处使用功能更新,因此您可以摆脱以下问题:function handleInput(&nbsp; answerHandler: (answer: number | null) => void,&nbsp; value: number,&nbsp; event: React.MouseEvent)解决这些问题后,更多问题出现在handleInput. 第一个是 thatevent.target可能不是一个元素,因此它的类型没有.parentNode. 在这种情况下,最好使用.currentTarget. 另请参阅javascript 中的 currentTarget 属性和 target 属性之间的确切区别是什么。修改后的函数为:function handleInput(&nbsp; answerHandler: (answer: number | null) => void,&nbsp; value: number,&nbsp; event: React.MouseEvent) {&nbsp; event.preventDefault();&nbsp; const parentEl = event.currentTarget.parentNode;&nbsp; const parentId = parentEl.getAttribute("id");&nbsp; if (parentId) {&nbsp; &nbsp; const el = document.getElementById(parentId);&nbsp; &nbsp; if (el) {&nbsp; &nbsp; &nbsp; for (let i = 0; i < el.children.length; i++) {&nbsp; &nbsp; &nbsp; &nbsp; if (el.children[i].classList.contains("selected")) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; el.children[i].classList.remove("selected");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; }&nbsp; event.currentTarget.classList.add("selected");&nbsp; answerHandler(value);}但是,唉,又出现了一个错误。这次是因为parentNode是类型Node。实际上有很多节点类型,“元素”只是其中之一!但显然,您实际上对父元素感兴趣,因此通过更改parentNode为parentElement,函数编译:function handleInput(&nbsp; answerHandler: (answer: number | null) => void,&nbsp; value: number,&nbsp; event: React.MouseEvent) {&nbsp; event.preventDefault();&nbsp; const parentEl = event.currentTarget.parentElement;&nbsp; const parentId = parentEl.getAttribute("id");&nbsp; if (parentId) {&nbsp; &nbsp; const el = document.getElementById(parentId);&nbsp; &nbsp; if (el) {&nbsp; &nbsp; &nbsp; for (let i = 0; i < el.children.length; i++) {&nbsp; &nbsp; &nbsp; &nbsp; if (el.children[i].classList.contains("selected")) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; el.children[i].classList.remove("selected");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; }&nbsp; event.currentTarget.classList.add("selected");&nbsp; answerHandler(value);}作为结束语,我只是一般性地说,这种直接的 DOM 操作在 React 世界中非常粗略,并且在大多数情况下可以而且应该用 React 来实现。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript