react+Hooks 的 useImperativeHandle 怎么用?

ref 的使用

普通的类组件有实例所以可以用过 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}/>
    }
}

useImperativeHandle 的使用

useImperativeHandle可以让你在使用ref时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用ref这样的命令式代码。useImperativeHandle应当与forwardRef一起使用。

 useImperativeHandle介绍

useImperativeHandle(ref, createHandle, [deps])
  • 通过useImperativeHandle可以只暴露特定的操作
    • 通过useImperativeHandle的Hook, 将父组件传入的ref和useImperativeHandle第二个参数返回的对象绑定到了一起
    • 所以在父组件中, 调用inputRef.current时, 实际上是返回的对象
  • useImperativeHandle使用简单总结:
    • 作用: 减少暴露给父组件获取的DOM元素属性, 只暴露给父组件需要用到的DOM方法
    • 参数1: 父组件传递的ref属性
    • 参数2: 返回一个对象, 以供给父组件中通过ref.current调用该对象中的方法

实例:

父组件:

import React, { useState, useEffect, useRef } from 'react';
 
 
const cRef = useRef() as React.MutableRefObject<any>;
 
 
//使用子组件暴露出来的方法   cRef.current
 
const handleAgree = async () => {
const res = await cRef.current.onFinish();
}
 
 
<Modal
   title="云端情报库"
   visible={isShow}
   onOk={handleAgree}
   onCancel={handleOff}
   destroyOnClose={true}
>
//CloudIntelligence 子组件
    <CloudIntelligence
       cRef={cRef}
       data={dataform}
     />
</Modal>

 子组件:

import React, { useState, useImperativeHandle, useEffect } from 'react';
 
 
//子组件解析出来
const { cRef, data } = props;
 
 
// 将方法暴露给父组件使用
useImperativeHandle(cRef, () => ({
   form,
   onFinish,
}));

回顾一下ref和forwardRef结合使用:

  • 通过forwardRef可以将ref转发给子组件
  • 子组件拿到父组件创建的ref, 绑定到自己的某一个元素中
import React, { useRef, forwardRef } from 'react'
 
// forwardRef可以将ref转发给子组件
const JMInput = forwardRef((props, ref) => {
  return <input type="text" ref={ref} />
})
 
export default function ForwardDemo() {
  // forward用于获取函数式组件DOM元素
  const inputRef = useRef()
  const getFocus = () => {
    inputRef.current.focus()
  }
 
  return (
    <div>
      <button onClick={getFocus}>聚焦</button>
      <JMInput ref={inputRef} />
    </div>
  )
}

forwardRef的做法本身没有什么问题, 但是我们是将子组件的DOM直接暴露给了父组件:

  • 直接暴露给父组件带来的问题是某些情况的不可控
  • 父组件可以拿到DOM后进行任意的操作
  • 我们只是希望父组件可以操作的focus,其他并不希望它随意操作其他方法

react hooks子组件向父组件传参(useContext) 

import React, { useState, useContext  } from 'react';
import { ChildrenContext } from '../index';
import { Button } from 'antd';
export const Children= (props) => {
    const { setParent } = props;
    const baseval = useContext(ChildrenContext);
    const onClick= () => {
        setParent(false);
    }
    return (
        <Button type="primary" onClick={()=>onClick()}>点击</Button>
    );
}

父组件:

import React, { useState, createContext } from 'react';
import {Children} from './Children.js';
export const ChildrenContext = createContext();
export const Parent = () => {
    const [parent, setChildren] = useState(false);
    return (
         <ChildrenContext.Provider value={parent}>
            <Children setParent={setChildren}/>
         </ChildrenContext.Provider>
    );
}

猜你喜欢

转载自blog.csdn.net/Z_Gleng/article/details/127310935