首页 > 解决方案 > 将反应回调引用与转发引用一起使用

问题描述

我有一个必须支持不确定状态的复选框反应组件,但我正在更新我们的组件以正确转发引用。复选框组件已在内部使用回调 ref 来设置不确定属性。这是原始组件(简化):

export type ICheckboxProps = {
  checked?: boolean
  indeterminate?: boolean
} & React.InputHTMLAttributes<HTMLInputElement>

export const Checkbox: React.FC<ICheckboxProps> = props => {
  const { checked = false, ...rest } = props;
  return (
    <input
      type="checkbox"
      checked={checked}
      ref={ref => {
        if (ref) {
          ref.indeterminate = !checked ? indeterminate! : false;
        }
      }}
      {...rest}
    />
  )
}

现在,由于这是一个 UI 库,我也在尝试转发一个 ref。但这与回调引用冲突 - 现在我有两个单独的引用。此外,转发的ref 可以是回调 ref。所以我什至无法访问那里的实例来设置不确定的属性。我尝试了很多东西,但无论我做什么打字稿有用的红色下划线告诉我我错了。

如何将转发的 ref 应用于输入并在输入上设置不确定属性?

这是大部分的方式,但有一个问题指出:

export type ICheckboxProps = {
  checked?: boolean
  indeterminate?: boolean
} & React.InputHTMLAttributes<HTMLInputElement>

export const Checkbox = React.forwardRef<HTMLInputElement, ICheckboxProps>((props, inRef) => {
  const { checked = false, ...rest } = props;
  return (
    <input
      type="checkbox"
      checked={checked}
      ref={ref => {
        if (ref) {
          ref.indeterminate = !checked ? indeterminate! : false;
          if (inRef) {
            if (typeof inRef === "function") {
              inRef(ref)
            } else {
              inRef.current = ref // Cannot assign to 'current' because it is a read-only property.
            }
          }
        }
      }}
      {...rest}
    />
  )
})

标签: javascriptreactjstypescript

解决方案


useImperativeHandle钩子与您的第二个示例几乎完全相同。ref.current然后由 React 在内部处理to的分配inRef,您不必通过更改 readonly 属性来破坏合同。

export const Checkbox = React.forwardRef<HTMLInputElement, ICheckboxProps>((props, inRef) => {
  const { checked = false, indeterminate, ...rest } = props;

  const ref = useRef<HTMLInputElement>(null)
  useImperativeHandle(inRef, () => ref.current!, [ref])

  return (
    <input
      type="checkbox"
      checked={checked}
      ref={ref}
      {...rest}
    />
  )
})

在打字稿游乐场

我想对ref.current. 据我所知,儿童的参考在父母的参考之前解决,但我能找到的文档中唯一相关的声明是在文档中调用inputRef.current.focus()没有空保护useImperativeHandle


推荐阅读