React forwardRef 和 TypeScript 中的各种属性

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

React forwardref and various Props in TypeScript

问题

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

I have a component like this

  1. interface FooProps{
  2. children: JSX.Element,
  3. id?: string,
  4. error?: boolean,
  5. width?: number,
  6. ref?: any
  7. }
  8. const Foo = forwardRef(({
  9. children,
  10. id,
  11. error,
  12. ref,
  13. width,
  14. }: FooProps) =&gt; {
  15. return &lt;ul
  16. id={id}
  17. ref={ref}
  18. style={{width: width, backgroundColor: error ? &#39;red&#39; . &#39;green&#39;}}&gt;
  19. {children}
  20. &lt;/ul&gt;
  21. })
  22. 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

  1. type Ref = any
  2. 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>(...)

示例:

  1. 接口 PopupAPI {
  2. 打开: () => void;
  3. 关闭: () => void;
  4. }
  5. 接口 PopupProps {
  6. children: React.ReactNode;
  7. 在关闭时?: () => void;
  8. 标题?: string;
  9. }
  10. 输出 const Popup= forwardRef<PopupAPI, PopupProps>(({ 在关闭时, children, 标题 }, ref) => {
  11. // useImperativeHandle(...);
  12. // ...
  13. });

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

  1. 接口 FooProps {
  2. children: React.ReactNode;
  3. 标识?: string;
  4. 错误?: boolean;
  5. 宽度?: number;
  6. }
  7. 输出 const Foo = forwardRef<HTMLElement, FooProps>(({children, 标识, 错误, 宽度}, ref) => (
  8. <ul id={标识} ref={ref}>
  9. {children}
  10. </ul>
  11. ));
英文:

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:

  1. interface PopupAPI {
  2. open: () =&gt; void;
  3. close: () =&gt; void;
  4. }
  5. interface PopupProps {
  6. children: React.ReactNode;
  7. onClose?: () =&gt; void;
  8. title?: string;
  9. }
  10. export const Popup= forwardRef&lt;PopupAPI, PopupProps&gt;(({ onClose, children, title }, ref) =&gt; {
  11. // useImperativeHandle(...);
  12. // ...
  13. });

and one example nearer to your use case:

  1. interface FooProps {
  2. children: React.ReactNode;
  3. id?: string;
  4. error?: boolean;
  5. width?: number;
  6. }
  7. export const Foo = forwardRef&lt;HTMLElement, FooProps&gt;(({children, id, error, width}, ref) =&gt; (
  8. &lt;ul id={id} ref={ref}&gt;
  9. {children}
  10. &lt;/ul&gt;
  11. ));

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:

确定