尝试在打字稿中使用 React useref 时出错

Posted

技术标签:

【中文标题】尝试在打字稿中使用 React useref 时出错【英文标题】:Error when trying to use React useref in typescript 【发布时间】:2020-09-17 22:39:54 【问题描述】:

使用 React 和 typescript 我正在构建一个选项卡组件,您可以在其中通过溢出从左到右滚动选项卡链接:滚动集。这适用于触控板,但我需要为鼠标用户实现一种方法,以便他们可以像在此代码笔中一样单击和滚动:https://codepen.io/thenutz/full/VwYeYEE 到目前为止,位于选项卡内容上方的选项卡链接的代码如下所示:

<div className='container'>
  <div className='flex-row'
    sx= overflow: 'scroll',
    '::-webkit-scrollbar':  display: 'none' ,
    display: flex,
    flexDirection: 'row',
    flexWrap: 'no-wrap' >
    <div className='tabLinks'
       sx=display: 'flex', flexDirection: 'row', flexWrap: 'no-wrap'>
      React.Children.map(children, (child, index) => ( //LOOPS THROUGH TAB LINKS HERE ))
    </div>
  </div>
</div>

tabLinks div 是需要同时通过触控板和鼠标水平滚动的 div(单击并拖动)

我第一次尝试这样做是使用 react useRef 为具有 ClassName 'tabLinks' 的 div 创建一个 ref

const ref = React.useRef<htmlDivElement>(null)

这个 ref 然后被传递给 tabLinks div,我尝试按照 codepen 示例实现 onMouseDown 事件,但在下面遇到了这个错误:

Property 'offsetLeft' does not exist on type 'RefObject<HTMLDivElement>'

任何帮助将不胜感激。

编辑:

这是我迄今为止尝试过的:

const ref = React.useRef<HTMLDivElement>(null)
  let startX
  let scrollLeft

<div className='container'>
  <div className='flex-row'
    sx= overflow: 'scroll',
    '::-webkit-scrollbar':  display: 'none' ,
    display: flex,
    flexDirection: 'row',
    flexWrap: 'no-wrap' >
        <div
          className='items'
          sx=
            display: 'flex', 
            flexDirection: 'row',
            flexWrap: 'no-wrap'
           
          ref=ref
          onMouseDown=e => 
            isDown= true
            const offset = ref.current?.offsetLeft || 0
            startX = e.pageX - offset
            scrollLeft = ref.current?.scrollLeft
          
          onMouseUp=e => 
            isDown = false;
          
          onMouseLeave=e => 
            isDown = false
          
          onMouseMove=e => 
            if(!isDown) return;
            e.preventDefault();
            const x = e.pageX - (ref.current?.offsetLeft ?? 0)
            const walk = (x - startX) * 3; //scroll-fast
            ref.scrollLeft = scrollLeft - walk
            console.log(walk)
          
        >
      React.Children.map(children, (child, index) => ( //LOOPS THROUGH TAB LINKS HERE ))
    </div>
  </div>
</div>

我现在收到这个错误

Uncaught TypeError: Cannot add property scrollLeft, object is not extensible
    at onMouseMove (index.tsx:102)
    at HTMLUnknownElement.callCallback (react-dom.development.js:149)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:199)
    at invokeGuardedCallback (react-dom.development.js:256)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:270)
    at executeDispatch (react-dom.development.js:561)
    at executeDispatchesInOrder (react-dom.development.js:583)
    at executeDispatchesAndRelease (react-dom.development.js:680)
    at executeDispatchesAndReleaseTopLevel (react-dom.development.js:688)
    at forEachAccumulated (react-dom.development.js:662)

【问题讨论】:

试试ref.current.offsetLeft 使用 ref.current.offsetLeft 会导致错误:“object is possible is null” 当然,它初始化为null,所以你只需要检查它是否为null。 ref.current?.offsetLeft @cbr 我对打字稿很陌生,我该怎么做? 【参考方案1】:

const offset = ref.current?.offsetLeft ?? 0;

同样的:

scrollLeft = ref.current?.scrollLeft ?? 0;

这样可以确保当当前 ref 为空时两个变量都有一个数值。

您将需要 null 合并运算符。如果您没有可用的,请使用:

const offset = ref.current?.offsetLeft || 0; scrollLeft = ref.current?.scrollLeft || 0;

【讨论】:

这解决了我面临的一个问题。我已经更新了我的原始帖子以显示所有代码。这就是我试图通过单击和拖动来实现滚动的方式。有什么帮助吗? 你从ref.current而不是ref获得当前的参考值 我哪里没有这样做? ref.scrollLeft

以上是关于尝试在打字稿中使用 React useref 时出错的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 react-router Link 访问 React 打字稿中的 props.location?

如何将 React useRef 钩子与打字稿一起使用?

React hook useRef 不适用于样式化组件和打字稿

是否可以在不使用 JSX 的情况下使用 React Hooks API(在打字稿中)

打字稿:React Native useRef 给出错误“对象可能为空”

当扩展与打字稿中的react-final-form FieldRenderProps接口时发生冲突