Использование 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
и я могу использовать самый короткий синтаксис.