Использование forwardRef с proptypes и eslint

Я пытаюсь использовать forwardRef для кнопки в проекте с использованием типов eslint и prop.

Это то, что я пробовал до сих пор, и каждый раз получаю ошибки:

Первая попытка

function Button ({ action = { callback: () => {}, title: 'unknown' } }, ref) {
  return (<button ref={ref} onClick={action.callback} title={action.description} type="button">{action.icon || action.title}</button>)
}

Button.propTypes = {
  action: Action.isRequired
}

export default forwardRef(Button)

Это даст мне следующее предупреждение в консоли: Warning: forwardRef render functions do not support propTypes or defaultProps. Did you accidentally pass a React component?

Вторая попытка

function ButtonFunction ({ action = { callback: () => {}, title: 'unknown' } }, ref) {
  return (<button ref={ref} onClick={action.callback} title={action.description} type="button">{action.icon || action.title}</button>)
}

const Button = forwardRef(ButtonFunction);

Button.propTypes = {
  action: Action.isRequired
}

export default ButtonFunction;

Я получил: action is missing in props validation.

Третья попытка

const Button = forwardRef(({ action = { callback: () => {}, title: 'unknown' } }, ref) => {
  return (<button ref={ref} onClick={action.callback} title={action.description} type="button">{action.icon || action.title}</button>)
});

Button.propTypes = {
  action: Action.isRequired
}

export default Button;

На этот раз я получаю: Component definition is missing display name.

Итак, как правильно это сделать?

4 ответа

Решение

Вы почти закончили свою третью попытку. Но вам не нужно использовать дваждыforwardRef, первое использование с Buttonдекларации достаточно. Правило отображаемого имени не является ошибкой (ни на уровне JavaScript, ни на уровне React), а скорее является преднамеренной опорой для отображения "настоящего" имени компонента, используемого React в сообщениях отладки. В вашем случаеforwardRef функция скроет "настоящее" имя компонента для транспайлера.

Вы даже можете отключить это правило, если написать displayName для каждого из этих случаев.

https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md

const Button = forwardRef(({ action = { callback: () => {}, title: 'unknown' } }, ref) => {
  return (<button ref={ref} onClick={action.callback} title={action.description} type="button">{action.icon || action.title}</button>)
});

Button.propTypes = {
  action: Action.isRequired
}

Button.displayName = 'Button'

export default Button

      const Form = React.forwardRef(function Form(
  { submitHandler, keyUpHandler, label, type, placeholder, buttonTxt },
  ref
) {

export default Form

Никаких предупреждений по этому поводу. function Form заботится об имени.

      interface SomeProps {
 // written your props
};

const SomeFC = forwardRef((props:SomeProps,ref)=>{
// do something and returns
}})

Объявление типа опор для внутреннего FC может исправить предупреждение о проптипах!

Ваша вторая попытка на самом деле была правильной, за исключением того факта, что вы экспортировали не ту вещь:

      function ButtonFunction({ action = { callback: () => {}, title: 'unknown' } }, ref)
{
  return (<button ref={ref} onClick={action.callback} title={action.description} type="button">{action.icon || action.title}</button>)
}

const Button = forwardRef(ButtonFunction);

Button.propTypes = {
  action: Action.isRequired
}

// export default ButtonFunction; // <-- you exported the inner function
export default Button; // <-- you should export the wrapped function

Мой совет — использовать одно и то же имя как для функции, так и для константной переменной. Таким образом, вы не сможете повторить ту же ошибку снова. Мы также можем немного сократить синтаксис.

      const Button = forwardRef(function Button({ action = { callback: () => {}, title: 'unknown' } }, ref)
{
  return (<button ref={ref} onClick={action.callback} title={action.description} type="button">{action.icon || action.title}</button>)
});

Button.propTypes = {
  action: Action.isRequired
}

export default Button;

Если вы не используете синтаксис, он становится намного короче:

      export default forwardRef(Button({ action = { callback: () => {}, title: 'unknown' } }, ref)
{
  return (<button ref={ref} onClick={action.callback} title={action.description} type="button">{action.icon || action.title}</button>)
})

Лично я предпочитаю использовать TypeScript для проверки параметров, так как в этом случае мне не нужноpropTypesи я могу использовать самый короткий синтаксис.

Другие вопросы по тегам