【问题标题】:Forwarding refs by multiple levels [Typescript / React]多级转发 refs [Typescript / React]
【发布时间】:2021-01-22 05:54:45
【问题描述】:

我正在尝试遵循原子设计原则,但我不确定我是否做得正确。 我创建了三个组件:Form、ExpandableInput 和 Input。输入是 HTML 输入包装器,可扩展输入是带下拉列表的输入,而表单只是表单。我想从 Form 组件访问当前输入值,所以我正在通过多个级别进行 ref 转发。在 Form 组件中一切正常,但问题是我必须在 ExpandableInput 组件中使用 ref.current.value,但出现以下错误。

类型“((实例: HTML输入元素 |空)=> 无效)|可变引用对象'。类型“(实例: HTML输入元素 | null) => 无效'。

我不知道如何告诉 typescript ExpandableInput 中的 ref 变量的类型为 Ref 并且不为空。不知道多级ref转发是不是好习惯,也许有更好的方法来获取输入值。

示例代码: 添加表单

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;

【问题讨论】:

  • 我认为你应该使用上下文而不是使用引用转发
  • "我不知道如何告诉 typescript ExpandableInput 中的 ref 变量的类型为 Ref 并且不为空",所以不要将 null 传递给 useRef,你也应该这样做一个沙盒你的问题
  • 如果你想访问输入值,不要使用 refs,使用状态,使你的输入受控组件

标签: javascript reactjs typescript


【解决方案1】:

forwardRef 收到的ref 实际上有三个可能的值。

type ForwardedRef<T> = ((instance: T | null) => void) | MutableRefObject<T | null> | null;

可以是null。它可能是您所期望的,它是由useRef 创建的MutableRefObject。第三种可能是callback function。 (注意:forwardRef 不支持旧版 string 引用)。

这三个中的任何一个都可以传递到下一个级别。但是如果我们想访问ref.current,那么我们需要确保我们拥有的是MutableRefObject。我们使用类型保护来做到这一点:if ( ref &amp;&amp; "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();
    }
}

Typescript Playground Link

【讨论】:

    猜你喜欢
    • 2020-01-14
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-22
    • 1970-01-01
    • 1970-01-01
    • 2020-08-28
    相关资源
    最近更新 更多