文章

函数组件获取子组件实例-forwardRef

函数组件获取子组件实例(forwardRef)

函数组件获取子组件实例-forwardRef

函数组件获取子组件实例(forwardRef)

基本用法

const Input = forwardRef((props, ref) => { const inputRef = useRef(null) return ( <div ref={inputRef}>hello</div> ) })

export default function Index() { const ipt = useRef(null) const handleClick = useCallback(() => ipt.current.focus(), [ ipt ]);

return ( <div> <Input ref={ipt}></Input> </div> ) }

useImperativeHandle

useImperativeHandleReact.forwardRef 必须是配合使用的。useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值

useImperativeHandle(ref, createHandle, [deps])

  • ref:定义 current 对象的 ref
  • createHandle:一个函数,返回值是一个对象,即这个 ref 的 current对象
  • [deps]:即依赖列表,当监听的依赖发生变化,useImperativeHandle 才会重新将子组件的实例属性输出到父组件\ ref 的 current 属性上,如果为空数组,则不会重新输出。

一个关于 ref 转发的例子

import React, { useState, useRef, useImperativeHandle, useCallback } from ‘react’; import ReactDOM from ‘react-dom’;

const FancyInput = React.forwardRef((props, ref) => { const [ fresh, setFresh ] = useState(false) const attRef = useRef(0); useImperativeHandle(ref, () => ({ attRef, fresh }), [ fresh ]);

const handleClick = useCallback(() => { attRef.current++; }, []);

return ( <div> {attRef.current} <button onClick={handleClick}>Fancy</button> <button onClick={() => setFresh(!fresh)}>刷新</button> </div> ) });

const App = props => { const fancyInputRef = useRef();

return ( <div> <FancyInput ref={fancyInputRef} /> <button onClick={() => console.log(fancyInputRef.current)} >父组件访问子组件的实例属性</button> </div> ) }

ReactDOM.render(, root);

ts版示例

/**

  • @component 通用筛选组件
  • @date 2022.9.6 */

import React, { useState, forwardRef, useImperativeHandle } from ‘react’ import { SearchColumnsType } from ‘@/types/common’ import { DownOutlined, UpOutlined } from ‘@ant-design/icons’ import { Button, Col, Form, Input, Row, Select, Cascader } from ‘antd’

interface IProps { columns: SearchColumnsType[] onSearch: (e: any) => void collapseNumber?: number }

const AdvancedSearchForm = forwardRef<any, IProps>((props, ref) => { const [expand, setExpand] = useState(false) const [form] = Form.useForm() const { columns, onSearch, collapseNumber = 7 } = props

useImperativeHandle(ref, () => ({ resetOtherFields }))

// 重置一组字段到 initialValues const resetOtherFields = (fields: any[]) => { form.resetFields(fields) }

const renderItem = (i: SearchColumnsType): any => { switch (i.type) { // 输入框 case ‘input’: return <Input placeholder={i.placeholder}/> // 选择器 case ‘select’: return <Select options={i.options} fieldNames={i.fieldNames} placeholder={i.placeholder} onChange={i.onChange} /> // 级联选择 case ‘cascader’: return <Cascader options={i.options} placeholder={i.placeholder}/> default: } }

const getFields = (): React.ReactElement => { const children: any = [] const columnsLen = columns.length const count = columnsLen > collapseNumber ? (expand ? columnsLen : collapseNumber) : columnsLen

1
2
3
4
5
6
7
8
9
10
11
12
13
columns.filter((c: any, cIndex: number) => cIndex < count).forEach((i: any) => {
  children.push(
    <Col span={6} key={i.key}>
      <Form.Item
        name={i.key}
        label={i.label}
      >
        {renderItem(i)}
      </Form.Item>
    </Col>
  )
})
return children   }

const onFinish = (values: any) => { onSearch(values) }

return ( <Form form={form} name=”advanced_search” className=”ant-advanced-search-form” onFinish={onFinish} > <Row gutter={24}> {getFields()}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    <Col span={6} style={{ marginBottom: 24 }}>

      <Button type="primary" htmlType="submit">查询</Button>
      <Button

        style={{ margin: '0 8px' }}

        onClick={() => {
          form.resetFields()
        }}
      >
        重置
      </Button>
      {
        columns.length >= collapseNumber && <a

          style={{ fontSize: 12 }}

          onClick={() => {
            setExpand(!expand)
          }}
        >
          {expand ? <UpOutlined/> : <DownOutlined/>} Collapse
        </a>
      }
    </Col>
  </Row>
  <Row>
  </Row>
</Form>   ) })

// displayName 属性用于为 React devtools 扩展的组件提供描述性名称 AdvancedSearchForm.displayName = ‘AdvancedSearchForm’ export default AdvancedSearchForm

本文由作者按照 CC BY 4.0 进行授权