如何通过数组传递ref到typescript中的forwardRef并做出反应?

时间:2020-06-16 09:37:10

标签: reactjs typescript

我有一个在Codepen中创建的示例。该表显示为th,但在我的IDE中,打字稿在此行抱怨类型:

<TH handleSort={handleSort} ref={refsTh[ind]}>

---错误类型'MutableRefObject'无法分配给类型'((实例:HTMLTableHeaderCellElement | null)=> void)| RefObject |空|未定义”。 类型“ MutableRefObject”不可分配给类型“ RefObject”。 属性“当前”的类型不兼容。 类型'unknown'不能分配给类型'HTMLTableHeaderCellElement |空值'。 无法将类型“未知”分配给类型“ HTMLTableHeaderCellElement”。

在不传递数组而是传递单个引用的情况下,我使此示例工作。问题似乎是因为我正在数组内部动态创建useRefs。有人可以请教吗?谢谢

示例代码: https://codepen.io/inspiraller/pen/OJMRZWQ

// import React from 'react';

// ######################################
type shapeTH = {
  handleSort: () => void,
  children: React.ReactNode // BUG: can't pass children any other way to forwardRef
};

type Ref = HTMLTableHeaderCellElement | null;

const TH = React.forwardRef<Ref, shapeTH>(
  ({children, handleSort}, ref) => (
    <th ref={ref} onClick={handleSort}>
      <span className="thSpan">{children}</span>
    </th>
  )
);

// const TH:React.FC<shapeTH> = ({children, handleSort}) => (
//   <th onClick={handleSort}>
//     <span className="thSpan">{children}</span>
//   </th>
// );

// ##################################################

const App:React.FC = () => {
  const arrTh=['id', 'name', 'colour'];

  type shapeRef = ReturnType<typeof React.useRef>;

  const refsTh: Array<shapeRef> = arrTh.map(() => (
    React.useRef<HTMLTableHeaderCellElement>(null)
  ));
  const handleSort: shapeTH['handleSort'] = () => {};
  return (
    <table className="tableGeneric">
      <thead>
        <tr>
          {
            arrTh.map((item, ind) => (
              <TH handleSort={handleSort} ref={refsTh[ind]}>
                {item}
              </TH>
            ))
          }
        </tr>
      </thead>
    </table>
  );
};

// export default App;

ReactDOM.render(
  <App/>,
  document.getElementById('app')
);


1 个答案:

答案 0 :(得分:0)

useRef 是一个泛型,你知道它是因为你正确地写了 React.useRef<HTMLParagraphElement>(null)。变量 refOne 的类型将被推断为 React.RefObject<HTMLParagraphElement>

问题是您手动为 refOne 分配了一个类型,这比这更模糊。当您查看 useRef 函数的返回类型时,您不知道它将用什么泛型类型调用,因此 type shapeRef = ReturnType<typeof React.useRef>React.MutableRefObject<unknown> 其中 unknown 是类型ref.current

当变量的类型从它们的值中知道时,您不需要手动为变量分配类型。这很好:

const App: React.FC = () => {
  const refOne = React.useRef<HTMLParagraphElement>(null);
  const handleSort = () => { };
  return (<P handleSort={handleSort} ref={refOne}>hello</P>);
};

Typescript Playground Link

对于您的数组示例,您有同样的问题。

const refsTh = arrTh.map(() => (
  React.useRef<Ref>(null)
));

Typescript Playground Link

仅供参考 #1:如果数组可以更改长度,您可能不想在数组上调用钩子,但是您的 App 有一个固定的数组,所以没问题。

仅供参考 #2:您可以使用 React.PropsWithChildren<P> 添加 children 道具。但是将其设置为常规道具也可以。