我们知道,对于子组件或者节点,如果是class类,存在实例,可以通过 React.createRef() 挂载到节点或者组件上,然后通过 this 获取到该节点或组件。

class RefTest extends React.Component{
constructor(props){
super(props);
this.myRef=React.createRef();
}
componentDidMount(){
console.log(this.myRef.current);
}
render(){
return <input ref={this.myRef}/>
}
}

  

但是在子组件是函数组件的时候,因为函数组件没有实例,所以在正常情况下, ref 是不能挂载函数组件上的。那么此时,我们通过 useImperativeHandle 和 forwardRef 配合就能达到效果。

useImperativeHandle

useImperativeHandle:可以配合 forwardRef 自定义暴露给父组件的实例值。

useImperativeHandle为我们提供了一个类似实例的东西,它帮助我们通过useImperativeHandle 的第二个参数,将所返回的对象的内容挂载到父组件的 ref.current 上.

useImperativeHandle 接收三个参数:

① 第一个参数 ref:接收 forWardRef 传递过来的 ref。
② 第二个参数 createHandle:处理函数,返回值作为暴露给父组件的 ref 对象
③ 第三个参数 deps:依赖项 deps,依赖项更改形成新的 ref 对象。
forwardRef 会创建一个 React 组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。

下面举一个实际例子,方便大家理解:

// 子组件

const CollectAmountFormItem = forwardRef(({ isDisabled, val, handleChange }: Props, onRef: any) => {

    const [isShow, setIsShow] = useState<boolean>(val == 1); // 是否展示募集资金和剩余募集资金

	// 暴露给父组件的属性
useImperativeHandle(onRef, () => ({
isShow,
setIsShow
})); useEffect(() => {
if (val == 1) setIsShow(true)
else setIsShow(false)
}, [val]) /**
* 是否募集回调
* @param val 下拉框id
* @param option 下拉框对象
*/
const handleSelect = (val: any, option: any) => {
setIsShow(val == 1);
handleChange && handleChange(val, option);
}; return (
<>
<Col xs={20} sm={16} md={12} lg={8} xl={6}>
<Form.Item name="isRaiseMoney" label="是否募集资金" rules={[{ required: true }]}>
<Select placeholder="请选择" disabled={isDisabled} onChange={handleSelect}>
<Select.Option value={1}>是</Select.Option>
<Select.Option value={0}>否</Select.Option>
</Select>
</Form.Item>
</Col>
{
isShow && (
<>
<Col xs={20} sm={16} md={12} lg={8} xl={6}>
<Form.Item name="usedMoney" label="已使用资金" rules={[{ required: isShow }]}>
<InputNumber
formatter={value => `${value}`.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,')}
parser={value => `${value}`.replace(/\$\s?|(,*)/g, '')}
style={{width: '100%'}}
precision={2}
disabled
placeholder="自动计算"
/>
</Form.Item>
</Col>
<Col xs={20} sm={16} md={12} lg={8} xl={6}>
<Form.Item name="remainMoney" label="剩余资金" rules={[{ required: isShow }]}>
<InputNumber
formatter={value => `${value}`.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,')}
parser={value => `${value}`.replace(/\$\s?|(,*)/g, '')}
style={{width: '100%'}}
precision={2}
disabled
placeholder="自动计算"
/>
</Form.Item>
</Col>
</>
)
}
</>
)
})

  

// 在父组件中使用

// 1、首先引入该子组件
import CollectAmountFormItem from '@/components/CollectAmountFormItem'; // 2、定义一个ref
const collectRef = useRef<any>() // 3、使用
<CollectAmountFormItem isDisabled={isDisable} val={formData.isRaiseMoney} ref={collectRef} handleChange={handleChangeAmount} /> // 然后就可以在父组件中的一些方法中获取子组件暴露出来的方法或值,比如: collectRef.current.setIsShow(false)

  

React-hooks 父组件通过ref获取子组件数据和方法的更多相关文章

  1. react 使用 redux 的时候 用 ref获取子组件的state

    由于 redux是无状态的,所以当我们在子组件中使用了 redux的时候,再父组件中,使用  ref 来获取子组件的state时,发现为一个空对象. 其实这个是有解决方案法的,原因在于 我们使用的 r ...

  2. React 函数式组件的 Ref 和子组件访问(useImperativeHandle)

    引入:如何调用函数式组件内部的方法 对于 React 中需要强制修改子组件的情况,React 提供了 Refs 这种解决办法,使得我们可以操作底层 DOM 元素或者自定的 class 组件实例.除此之 ...

  3. 九、React中的组件、父子组件、React props父组件给子组件传值、子组件给父组件传值、父组件中通过refs获取子组件属性和方法

    一.概述 React中的组件: 解决html 标签构建应用的不足. 使用组件的好处:把公共的功能单独抽离成一个文件作为一个组件,哪里里使用哪里引入. [父子组件]:组件的相互调用中,我们把调用者称为父 ...

  4. React Hook父组件获取子组件的数据/函数

    我们知道在react中,常用props实现子组件数据到父组件的传递,但是父组件调用子组件的功能却不常用.文档上说ref其实不是最佳的选择,但是想着偷懒不学redux,在网上找了很多教程,要不就是hoo ...

  5. vue 父组件主动获取子组件的数据和方法 子组件主动获取父组件的数据和方法

    Header.vue <template> <div> <h2>我是头部组件</h2> <button @click="getParen ...

  6. vue父组件中获取子组件中的数据

    <FormItem label="上传头像" prop="image"> <uploadImg :width="150" ...

  7. Vue 父组件主动获取子组件的值,子组件主动获取父组件的值

    父组件主动获取子组件的值 1. 在调用子组件的时候定义一个ref-> ref="header"2. 在父组件中通过this.$refs.header.属性,调用子组件的属性, ...

  8. Vee-validate 父组件获取子组件表单校验结果

    vee-validate 是为 Vue.js 量身打造的表单校验框架,允许您校验输入的内容并显示对应的错误提示信息.它内置了很多常见的校验规则,可以组合使用多种校验规则,大部分场景只需要配置就能实现开 ...

  9. vue父组件获取子组件页面的数组 以城市三级联动为例

    父组件调用子组件 <Cselect ref="registerAddress"></Cselect> import Cselect from '../../ ...

  10. vue.js 父组件主动获取子组件的数据和方法、子组件主动获取父组件的数据和方法

    父组件主动获取子组件的数据和方法 1.调用子组件的时候 定义一个ref <headerchild ref="headerChild"></headerchild& ...

随机推荐

  1. DRF_基本使用

    基本使用 视图内 from rest_framework.viewsets import ModelViewSet from app01 import models from app01 import ...

  2. 一文带你吃透Redis

    目录 1. 基本数据结构 2. 数据持久化 3. 高可用 4. 缓存 文章字数大约1.9万字,阅读大概需要66分钟,建议收藏后慢慢阅读!!! 1. 基本数据结构 什么是Redis Redis是一个数据 ...

  3. 人人皆可虚拟,直播还能这么玩?声网推出 MetaLive 元直播解决方案

    视频群聊.在线社交.电商带货.游戏竞技.......越来越多的场景融入了直播这一功能.无可厚非,直播可以拉近人与人间的距离,让彼此间的交流更具象.但传统直播场景更为强调主播个人的表现,用户多以围观.刷 ...

  4. PHP微信三方平台-授权登录

    一.逻辑步骤解析 步骤 1:第三方平台方获取预授权码(pre_auth_code) 步骤 2:引入用户进入授权页 第三方平台方可以在自己的网站中放置"微信公众号授权"或者" ...

  5. cron语句

    名称 是否必须 允许值 特殊字符 秒 是 0-59 , - * / 分 是 0-59 , - * / 时 是 0-23 , - * / 日 是 1-31 , - * ? / L W C 月 是 1-1 ...

  6. Json和对象之间的转换

    JSON是一种字符: json转对象: var str = '{"name":"admin","age":16,"sex" ...

  7. Kubernetes(k8s)实现IPv4/IPv6网络双栈

    背景 如今IPv4IP地址已经使用完毕,未来全球会以IPv6地址为中心,会大力发展IPv6网络环境,由于IPv6可以实现给任何一个设备分配到公网IP,所以资源是非常丰富的. 配置hosts [root ...

  8. Containerd 入门基础操作

    Containerd 被 Docker.Kubernetes  CRI 和其他一些项目使用 Containerd 旨在轻松嵌入到更大的系统中.Docker 在后台使用 containerd来运行容器. ...

  9. 从APNIC获取中国IP地址列表

    关于APNIC 全球IP地址块被IANA(Internet Assigned Numbers Authority)分配给全球三大地区性IP地址分配机构,它们分别是: ARIN (American Re ...

  10. 四月十五号java基础知识

    1.今天下午做了一个题感受很深,自己做题没有思路或者有点思路死磕也没有搞清楚,看起来很简单的问题,在我手里很难 做咯许久还是室友帮忙解决的,后面重新打一遍还是出问题,找他解决的,问了问他我自己的问题, ...