React forwardRef 和 TypeScript 中的各种属性

huangapple go评论61阅读模式
英文:

React forwardref and various Props in TypeScript

问题

type Ref = any
forwardRef<Ref, FooProps>((props, ref) => {...})
英文:

I have a component like this

interface FooProps{
    children: JSX.Element,
    id?: string,
    error?: boolean,
    width?: number,
    ref?: any
}

const Foo = forwardRef(({
                     children,
                     id,
                     error,
                     ref,
                     width,
                 }: FooProps) =&gt; {
    return &lt;ul
        id={id}
        ref={ref}
        style={{width: width, backgroundColor: error ? &#39;red&#39; . &#39;green&#39;}}&gt;
        {children}
    &lt;/ul&gt;
})

export default Foo;

Now, the compiler complains that forwardRef() only accepts two parameters, props and ref.
How would I tell TypeScript that the shape props is the shape of FooProps? This

type Ref = any
forwardRef(&lt;Ref, FooProps&gt;((props, ref)) =&gt; {...})

Does not work.

答案1

得分: 1

你的代码中有几个需要注意的地方:

  • 在使用 forwardRef 时,ref 不是 props 的一部分。它是渲染函数的第二个参数。我知道这有点不直观,但目前是这样的(React 团队内部可能有讨论要更改这一点)。
  • 我建议在声明组件属性中的 children 时,始终使用 React.ReactNode,以确保能够匹配任何可以作为任何渲染函数的有效返回值的内容,包括 nullstring
  • forwardRef 提供类型是在括号之前进行的:forwardRef<Type-of-ref, Type-of-Props>(...)

示例:

接口 PopupAPI {
  打开: () => void;
  关闭: () => void;
}

接口 PopupProps {
  children: React.ReactNode;
  在关闭时?: () => void;
  标题?: string;
}

输出 const Popup= forwardRef<PopupAPI, PopupProps>(({ 在关闭时, children, 标题 }, ref) => {
  // useImperativeHandle(...);
  // ...
});

另一个与您的用例更接近的示例:

接口 FooProps {
    children: React.ReactNode;
    标识?: string;
    错误?: boolean;
    宽度?: number;
}

输出 const Foo = forwardRef<HTMLElement, FooProps>(({children, 标识, 错误, 宽度}, ref) => (
  <ul id={标识} ref={ref}>
    {children}
  </ul>
));
英文:

There are several things that need to be addressed in your code:

  • when using forwardRef the ref is not part of the props. It is a second argument to the render function. I know this is unintuitive but that's the way it is currently (there is or was some discussion within the react team to change this)
  • I recommend to use React.ReactNode whenever you declare children in component props, to actually match anything that could count as valid return value of any render function, including null or string.
  • providing types to forwardRef is done before the parentheses: forwardRef&lt;Type-of-ref, Type-of-Props&gt;(...)

An example:

interface PopupAPI {
  open: () =&gt; void;
  close: () =&gt; void;
}

interface PopupProps {
  children: React.ReactNode;
  onClose?: () =&gt; void;
  title?: string;
}

export const Popup= forwardRef&lt;PopupAPI, PopupProps&gt;(({ onClose, children, title }, ref) =&gt; {
  // useImperativeHandle(...);
  // ...
});

and one example nearer to your use case:

interface FooProps {
    children: React.ReactNode;
    id?: string;
    error?: boolean;
    width?: number;
}

export const Foo = forwardRef&lt;HTMLElement, FooProps&gt;(({children, id, error, width}, ref) =&gt; (
  &lt;ul id={id} ref={ref}&gt;
    {children}
  &lt;/ul&gt;
));

huangapple
  • 本文由 发表于 2023年5月26日 16:52:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76339192.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定