首页 > 网络编程 > JavaScript > javascript类库 > React > React.forwardRef传递泛型参数

使用React.forwardRef传递泛型参数

作者:Joey_Tribiani

这篇文章主要介绍了使用React.forwardRef传递泛型参数方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

React.forwardRef传递泛型参数

使用React函数组件开发的过程中会遇到父组件调用子组件的方法或者属性的场景,首次先说怎么通过React.forwardRef来将子组件的属性或者方法暴露给父组件

使用forwardRef暴露组建的方法和属性

import { Box, Typography } from "@mui/material";
import { forwardRef, useImperativeHandle } from "react";
interface LocationChildProps {
  data: string;
export interface LocationChildRef {
  sayType(): void;
const LocationChild = forwardRef<LocationChildRef, LocationChildProps>((props, ref) => {
  useImperativeHandle(ref, () => ({
    sayType() {
      console.log("子组件的data是 " + typeof props.data);
  return (
      <Typography>{typeof props.data}</Typography>
export default LocationChild;

在子组件中我们需要接受一个key为data的props,然后在子组件中展示这个值,并且通过useImperativeHandle向外暴露一个sayType的方法, 最后用forwardRef将子组件封装然后暴露出去,这里forwardRef的作用就是包装该组件为一个可以通过Ref访问的组件。

import { Button } from "@mui/material";
import { useRef } from "react";
import ConfigDetailContainer from "../options/ConfigDetailContainer";
import LocationChild, { LocationChildRef } from "./LocationChild";
export default function DeviceLocation() {
  const locationChildRef = useRef<LocationChildRef>();
  const handleClick = () => {
    locationChildRef.current.sayType()
    // 输出: 子组件的type是 string  
  return (
    <ConfigDetailContainer title="device.configTabs.LOCATION_HISTORY">
      <LocationChild ref={locationChildRef} data="asdafaf"></LocationChild>
      <Button onClick={handleClick}>查看子组件的type的类型</Button>
    </ConfigDetailContainer>

父组件中需要通过useRef来创建ref并传递给子组件,这样父子组件就建立了连接,父组件可以通过ref来访问子组件中自定义暴露的属性或方法。

这里的操作就是父组件点击按钮控制台打印子组件接收到的data这个prop的类型。

现在新的问题就是我们的父组件传递的data的类型不是固定的,这时候子组件就要将data的类型用泛型来定义,所以这里就有了fowardRef传递泛型参数的问题:

我们可以这样改造子组件,思路就是将这个组件改为工厂hansh的生成模式:

import { Box, Typography } from "@mui/material";
import { forwardRef, useImperativeHandle } from "react";
export interface LocationChildProps<T = string> {
  data: T;
export interface LocationChildRef {
  sayType(): void;
const LocationChild = function <T>() {
  return forwardRef<LocationChildRef, LocationChildProps<T>>((props, ref) => {
    useImperativeHandle(ref, () => ({
      sayType() {
        console.log("子组件的data是 " + typeof props.data);
    return (
        <Typography>{typeof props.data}</Typography>
export default LocationChild;

然后在父组件中使用

import { Button } from "@mui/material";
import { PropsWithRef, useRef } from "react";
import ConfigDetailContainer from "../options/ConfigDetailContainer";
import LocationChild, { LocationChildProps, LocationChildRef } from "./LocationChild";
export default function DeviceLocation() {
  const locationChildRefString = useRef<LocationChildRef>();
  const locationChildRefBoolean = useRef<LocationChildRef>();
  const handleClick = () => {
    locationChildRefString.current.sayType();
    locationChildRefBoolean.current.sayType();
  const LocationChildComponent = LocationChild<string>();
  const createComponent = function <T>(props: PropsWithRef<any>, ref: React.MutableRefObject<LocationChildRef>) {
    const Mycomponent = LocationChild<T>();
    return <Mycomponent ref={ref} {...props}></Mycomponent>;
  return (
    <ConfigDetailContainer title="device.configTabs.LOCATION_HISTORY">
      <LocationChildComponent ref={locationChildRefString} data={"123"}></LocationChildComponent>
      {createComponent({ data: true }, locationChildRefBoolean)}
      <Button onClick={handleClick}>查看子组件的type的类型</Button>
    </ConfigDetailContainer>

我们可以直接调用LocationChild方法生成组件,也可以再度封装为createComponent这样的方法,这样就实现了forwardRef中使用泛型参数的需求。

react forwardRef 导致 泛型丢失

网上没有找到合适的方案,看了 antd 的源码

实现方式如下

const ForwardTable = React.forwardRef(InternalTable) as <RecordType extends object = any>(
  props: React.PropsWithChildren<TableProps<RecordType>> & { ref?: React.Ref<HTMLDivElement> },
) => React.ReactElement;
// so u can use
<Table<{id: string, b: number}>  />

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
  • 如何在React Native开发中防止滑动过程中的误触
    如何在React Native开发中防止滑动过程中的误触
    2023-05-05
  • 使用React和Redux Toolkit实现用户登录功能
    使用React和Redux Toolkit实现用户登录功能
    2023-05-05
  • react fiber使用的关键特性及执行阶段详解
    react fiber使用的关键特性及执行阶段详解
    2023-05-05
  • 重新理解 React useRef原理
    重新理解 React useRef原理
    2023-05-05
  • react hooks深拷贝后无法保留视图状态解决方法
    react hooks深拷贝后无法保留视图状态解决方法
    2023-05-05
  • 用React实现一个类 chatGPT 的交互式问答组件的方法详解
    用React实现一个类 chatGPT 的交互式问答组件
    2023-05-05
  • React Fiber中面试官最关心的技术话题
    React Fiber中面试官最关心的技术话题
    2023-05-05
  • React通过useContext特性实现组件数据传递
    React通过useContext特性实现组件数据传递
    2023-05-05
  • 美国设下计谋,用娘炮文化重塑日本,已影响至中国
    美国设下计谋,用娘炮文化重塑日本,已影响至中国
    2021-11-19
  • 时空伴随者是什么意思?时空伴随者介绍
    时空伴随者是什么意思?时空伴随者介绍
    2021-11-09
  • 工信部称网盘企业免费用户最低速率应满足基本下载需求,天翼云盘回应:坚决支持,始终
    工信部称网盘企业免费用户最低速率应满足基本下载需求,天翼云盘回应:坚决支持,始终
    2021-11-05
  • 2022年放假安排出炉:五一连休5天 2022年所有节日一览表
    2022年放假安排出炉:五一连休5天 2022年所有节日一览表
    2021-10-26
  • 电脑版 - 返回首页

    2006-2023 脚本之家 JB51.Net , All Rights Reserved.
    苏ICP备14036222号