夜猫子的知识栈 夜猫子的知识栈
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

夜猫子

前端练习生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 核心概念

  • 高级指引

  • Hook

  • 案例演示

  • Router

  • Redux

  • Jotai

  • Mobx

  • 其他

    • React使用经验
    • React的重新渲染详解
    • forwardRef和useImperativeHandle
      • 1.转发refs到DOM组件
      • 2.在高阶组件中转发 refs
    • SWR去除重复请求
    • React封装拖拽组件
    • React实现分页打印
  • 《React》笔记
  • 其他
夜猫子
2023-05-23
目录

forwardRef和useImperativeHandle

# forwardRef

React.forwardRef字面意思理解为转发Ref,它会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。其主要作用是:

# 1.转发refs到DOM组件

ref 不像 props 作为参数可以传递,所以要想传递 ref 得用 forwardRef。

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = useRef(null);

const Father=()=>{
    const handleClick=()=>{
        const RefValue = ref.current
        RefValue.handleCancel() // 可以直接使用被转发的方法
    }
    return (
        <button onClick={handleClick}>
        <FancyButton ref={ref}>Click me!</FancyButton>;
    )
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

因此,当 React 附加了 ref 属性之后,ref.current 将直接指向 DOM 元素实例。

如果一个组件被多次使用,正常情况下想要调用其组件内的方法需要传入props来调用,每次传入的话就比较多余。所以就引入了React.forwardRef。(在tsx中的运用)。

interface SelectFileModalRef {
  handleShowModal: () => void;
  handleCancel: () => void;
}
const SelectFileModal = forwardRef<SelectFileModalRef, Props>(
  (props: Props, ref: Ref<SelectFileModalRef>) => {
   useImperativeHandle(ref, () => ({
      handleShowModal,
      handleCancel,
    }));
  }
);
1
2
3
4
5
6
7
8
9
10
11
12

子组件暴露出来的handleShowModal和handleCancel在父组件就可以使用selectFileModalRef.current?.handleShowModal() 来调用进行使用。

# 2.在高阶组件中转发 refs

首先要搞清楚什么是高阶组件:高阶组件(HOC)它是一种基于 React 的组合特性而形成的设计模式。

具体而言,高阶组件是参数为组件,返回值为新组件的函数

// 此函数接收一个组件...
function withSubscription(WrappedComponent, selectData) {
  // ...并返回另一个组件...
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.handleChange = this.handleChange.bind(this);
      this.state = {
        data: selectData(DataSource, props)
      };
    }

    componentDidMount() {
      // ...负责订阅相关的操作...
      DataSource.addChangeListener(this.handleChange);
    }

    componentWillUnmount() {
      DataSource.removeChangeListener(this.handleChange);
    }

    handleChange() {
      this.setState({
        data: selectData(DataSource, this.props)
      });
    }

    render() {
      // ... 并使用新数据渲染被包装的组件!
      // 请注意,我们可能还会传递其他属性
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  };
}
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
31
32
33
34

如果你对 HOC 添加 ref,该 ref 将引用最外层的容器组件,而不是被包裹的组件。

此时需要用到forwardRef

function logProps(Component) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      const {forwardedRef, ...rest} = this.props;

      // 将自定义的 prop 属性 “forwardedRef” 定义为 ref
      return <Component ref={forwardedRef} {...rest} />;
    }
  }

  // 注意 React.forwardRef 回调的第二个参数 “ref”。
  // 我们可以将其作为常规 prop 属性传递给 LogProps,例如 “forwardedRef”
  // 然后它就可以被挂载到被 LogProps 包裹的子组件上。
  return React.forwardRef((props, ref) => {
    return <LogProps {...props} forwardedRef={ref} />;
  });
}

const ref=useref(null)
logProps(<Component data style forwardedRef={ref} />)
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
编辑 (opens new window)
上次更新: 2023/8/22 19:22:36
React的重新渲染详解
SWR去除重复请求

← React的重新渲染详解 SWR去除重复请求→

最近更新
01
IoC 解决了什么痛点问题?
03-10
02
如何调试 Nest 项目
03-10
03
Provider注入对象
03-10
更多文章>
Copyright © 2019-2025 Study | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式