Как правильно использовать forwardRef в Typescript?

#javascript #reactjs #typescript

Вопрос:

Я очень новичок в React, пожалуйста, потерпите меня

У меня есть компонент

 const Avatar = forwardRef((props, ref) => {
  const {
    color,
    className,
    size,
    tag: Tag,
    ...rest
  } = props

  return (
    <Tag
      className={classnames('avatar', {
        [className]: className,
        [`bg-${color}`]: color,
        [`avatar-${size}`]: size
      })}
      ref={ref}
      {...rest}
    >
      ... //rest of codes
    </Tag>
  )
})

export default Avatar
 

Теперь я могу сделать это в javascript

 <Avatar size="sm" color="success" />
 

Однако в Typescript я буду получать сообщение об ошибке

 Property 'size' does not exist on type 'IntrinsicAttributes amp; RefAttributes<any>'  
 

Есть идеи, что пошло не так? Я предполагаю, что мне нужно передать ref , поэтому я делаю

 const ref = React.createRef<Tag>();
<Avatar ref={ref} size="sm" color="success" />  
 

Но у меня все еще такая же проблема, как мне передать size и color в качестве реквизита? Я пытался искать ответ в Интернете и так далее, но, похоже, не могу найти решение, любая помощь будет оценена.

Комментарии:

1. реквизит не может использоваться как JSX. Этот фрагмент кода <Tag> . . . </Tag> недопустим. Если вы передаете тег в качестве реквизита, вы должны импортировать его вместо этого.

Ответ №1:

Я не уверен, действительно ли вам нужно пересылать ref или нет. Я надеюсь, что мой ответ даст вам какой-то способ решить ваш вариант использования. Я вижу, что вы передаете Tag как prop и используете его как недопустимый тег JSX.

Объясните мне, что этот фрагмент кода JSX недопустим

 <Tag
  className={classnames('avatar', {
    [className]: className,
    [`bg-${color}`]: color,
    [`avatar-${size}`]: size
  })}
  ref={ref}
  {...rest}
>
  ... //rest of codes
</Tag>
 

поскольку вы передаете Tag как prop, вы не можете использовать его как тег JSX. Вы можете передать тег JSX в качестве реквизита, но реализация не такова. Вы должны импортировать этот тег вместо этого или, если вы действительно хотите передать его как prop. вам нужно создать его в его родительском компоненте.

Вот так

 const ParentComponent: React.FC = () => (
  <Avatar
    // You have to compose it here

    tag={
      <Tag
      // className={classnames('avatar', {
      //   [className]: className,
      //   [`bg-${color}`]: color,
      //   [`avatar-${size}`]: size
      // })}
      // ref={ref}
      // {...rest}
      >
        ... //rest of codes
      </Tag>
    }
  />
);

export default ParentComponent;
 

Вы также можете взаимодействовать с демонстрацией в codesandbox, чтобы лучше понять, что я пытаюсь сказать. Просто нажмите здесь

Ответ №2:

добавление forwardRef при экспорте устраняет ошибки TSLint

 const Avatar = (props, ref) => {
const {
 color,
 className,
 size,
 tag: Tag,
 ...rest
} = props

return (
  <Tag
  className={classnames('avatar', {
    [className]: className,
    [`bg-${color}`]: color,
    [`avatar-${size}`]: size
  })}
  ref={ref}
  {...rest}
  >
  ... //rest of codes
  </Tag>
 )
}

export default forwardRef(Avatar)