我正在努力遵循原子设计原则,但我不确定我做得是否正确。我创建了三个组件:Form、ExpandableInput和Input。Input是HTML输入包装器,Expandable输入是带下拉框的Input,Form只是表单。我想从Form组件访问当前输入值,所以我正在进行多级引用转发。Form组件中的一切都很好,但问题是我必须在ExpandableInput组件中使用ref.current.value,但我收到了以下错误。
类型"上不存在属性"current"((实例:HTMLInputElement|null(=>void(|MutableRefObject<HTML输入元素|null>'。类型"上不存在属性"current"(实例:HTMLInputElement|null(=>void。
我不知道如何告诉typescript ExpandableInput中的ref变量的类型为ref,并且不是null。我不知道多个级别的ref转发是否是一种好的做法,也许有更好的方法来获得输入值。
示例代码:AddForm
const Form = () => {
// Refs
const caRef = useRef<HTMLInputElement>(null);
return (
<FormTemplate >
<ExpandableInput
option={CompetenceAreaOption}
ref={caRef}
/>
</FormTemplate>
);
}
export default AddForm;
可扩展输入
const ExpandableInput = React.forwardRef<HTMLInputElement, IProps>((
props,
ref
): JSX.Element => {
const pickInputValue = (value: string): void => {
console.log(ref.current) // Error
console.log(ref) // Input reference
}
}
return (
<div>
<div>
<Input
ref={ref}
/>
</div>
</div>
);
})
export default ExpandableInput;
输入
const Input = React.forwardRef<HTMLInputElement, IProps>(({
props,
ref
): JSX.Element => {
return (
<input
ref={ref}
/>
);
})
export default Input;
forwardRef
接收到的ref
实际上有三个可能的值。
type ForwardedRef<T> = ((instance: T | null) => void) | MutableRefObject<T | null> | null;
它可以是null
。它可以是您所期望的,它是由useRef
创建的MutableRefObject
。第三种可能性是它可以是一个回调函数。(注意:forwardRef
不支持传统的string
引用(。
这三个人中的任何一个都可以晋级下一个级别。但如果我们想访问ref.current
,那么我们需要确保我们拥有的是MutableRefObject
。我们使用类型保护:if ( ref && "current" in ref)
来完成此操作。这样就可以访问ref.current
。
ref.current
可能是null
(当ref还没有附加到DOM时(。因此,我们还需要检查current
是否与if
或可选的链式运算符?.
有效
简称:
if ( ref && "current" in ref) {
ref.current?.focus();
}
长版本:
// make sure that ref is a MutableRefObject
if (ref && "current" in ref) {
// input has type HTMLInputElement | null
const input = ref.current;
// exlude null current value
if (input) {
// now we know that we have an input
input.focus();
}
}
打字游戏场链接