将React回调ref与转发的ref一起使用

时间:2019-07-30 18:37:48

标签: javascript reactjs typescript

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

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。此外,转发引用可以是回调引用。因此,我什至无法访问那里的实例来设置不确定的属性。我已经尝试了很多东西,但是无论我做什么,打字稿的红色底线都会告诉我我错了。

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

在大多数情况下都是这样,但是有一个问题要指出:

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}
    />
  )
})

2 个答案:

答案 0 :(得分:3)

>>> pd.show_versions() INSTALLED VERSIONS ------------------ commit : None python : 3.8.0.final.0 python-bits : 64 ... many lines omitted ... xlrd : 1.2.0 xlwt : 1.3.0 xlsxwriter : 1.2.2 >>> pd.show_versions(as_json=True) {'system': {'commit': None, ... , 'LOCALE': 'en_US.UTF- 8'}, 'dependencies': {'pandas': '0.25.2', ... , 'xlwt': '1.3.0'}} 钩子与第二个示例几乎完全相同。然后,useImperativeHandleref.current的分配是由React内部处理的,您不必通过更改readonly属性来破坏合同。

inRef

In typescript playground

我想评论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} /> ) }) 上的非null断言。据我所知,对孩子的引用在对父母的引用之前已得到解决,但是我能找到的文档中唯一相关的声明是调用ref.current,而在documentation of useImperativeHandle

中没有空保护

答案 1 :(得分:0)

您可以对转发的引用进行任何操作,包括设置其当前值:

const Checkbox = React.forwardRef(({ checked = false, indeterminate, ...rest }, forwardedRef) => (
  <input
    type="checkbox"
    checked={checked}
    ref={(inputElement) => {
      if (inputElement) {
        inputElement.indeterminate = !checked && indeterminate
      }

      if (forwardedRef) {
        if(typeof(forwardedRef) !== "function") {
          forwardedRef(inputElement)
      } else {
        forwardedRef.current = inputElement
      }
    }
    {...rest}
  />
))