美文网首页
React 泛型组件是什么?

React 泛型组件是什么?

作者: littleyu | 来源:发表于2023-06-20 10:37 被阅读0次

案例

假设我们要做一个很简单的 Show 组件,用法如下:

<Show 
  content="hi" 
  onClick={c => console.log(c)}
/>

Show 组件会展示 content,并在用户点击 content 时把 content 传给 onClick。

因此代码中的 c 和 content 总是相等的。

你会如何实现 Show 组件呢?假设你是这么写的:

interface Props{
  content: any
  onClick?: (arg: any) => void
}

function Show(props: Props){
  const {content, onClick} = props
  return (
    <div>
      {content}
      <button 
        onClick={()=> onClick?.(content)}
      >
        Click me
      </button>
    </div>
  )
}

确实能完成功能,但是用到了两个 any,这不是 TypeScript,这是 AnyScript。

改写

于是你可以打算进行改写,你发现 content 和 onClick 的参数其实总是一样的,于是你写成这样:

interface Props<T>{
  content: T
  onClick?: (arg: T) => void
}

但此时,Show 报错了:

报错内容是 Props 需要接受一个参数 T,于是你让 Show 接受一个参数 T,再把 T 传给 Props:

function Show<T>(props: Props<T>){ ...

报错消除了。

于是 Show 组件就可以这样用了:

<Show<string> 
  content="hi" 
  onClick={c => console.log(c)}/>

由于 TypeScript 有自动推断功能,所以可以从 content 自动推断出 T = string,所以可以简写成这样:

<Show
  content="hi" 
  onClick={c => console.log(c)}/>

这种写法跟最开始的写法一模一样,但是我们得到了一个大好处:c 的类型不再是 any 了,而是跟 content 保持一致:

以上,就是泛型组件的简单演示。

不过值得注意的是,上面的 Show 被我声明为普通函数,并没有被声明为 React.FunctionComponent,因为一旦声明成 React.FunctionComponent,就没法再加泛型了。

另外,如果你喜欢用 Class 组件,那么可以把 Show 组件写成这样:

class Show<T> extends Component<Props<T>> {
  render(){
    return (
    <div>
      {this.props.content}
      <button 
        onClick={
          ()=> this.props.onClick?.(this.props.content)}
      >
        Click me
      </button>
    </div>
    )
  }
}

export default function App() {
  return (
    <Show content='hi' onClick={c => console.log(c)} />
  );
}

实际场景

在实际工作中,我们什么时候会遇到泛型组件呢?这里有一个典型的例子:Table 组件。

假设我们的 Table 组件是这样用的:

<Table
  data={[
    {id:1, name:'Alice',age:16,gender:'女'},
    {id:2, name:'Bob',age:16,gender:'男'},
    {id:3, name:'Carry',age:16,gender:'男'},
  ]}
  cols={[
    {key:'name', title:'姓名'},
    {key:'age', title:'年龄'}
  ]}
/>

三条数据,只展示 name 和 age,我们如何确保 cols 里的 key 一定是 data 里面的字段名呢?

用泛型即可:

  data: T[],
  cols: {
    key: keyof T // cols 的 key 必须是 data item 的字段名
    title: string
  }[]
}

function Table <T>(props: Props<T>) {
  const {data, cols} = props
  return (
    <table>
      {data.map(d => 
        <tr>
          {cols.map(c => 
            <td>{d[c.key]}</td>  
          )}
        </tr>
      )}
    </table>
  )
}

也就是说,当你需要两个 props 的类型有关联的时候,往往可以使用泛型组件来实现。

不解

不过目前我很疑惑下面这段代码翻译成 TypeScript 是怎样的:

<Show<string> />

虽然我知道这段代码翻译成 JavaScript 是

React.createElement(Show)
// 或
_jsx(Show)

但我并不知道翻译成 TypeScript 应该怎么写,尤其是 <string> 会被放在哪。

如果你知道,请不吝赐教。

相关文章

  • React 组件浅析

    组件可以是一个函数(React) 组件分类: 纯展示型 接入型 container (React) 交互型组件,各...

  • TypeScript 06 - 泛型

    基本示例 使用泛型变量 泛型类型 泛型类 泛型约束 1. 基本示例 考虑到组件的可重用性,引入了泛型的概念,可以使...

  • 泛型

    泛型 Why:为什么需要泛型 What:泛型是什么; How:泛型怎么实现 When:泛型什么时候使用 Where...

  • 泛型(一)

    1. Java中的泛型是什么 ? 使用泛型的好处是什么? 泛型是Java SE 1.5的新特性,泛型的本质是参数化...

  • 赢在面试之Java泛型篇

    1、Java中的泛型是什么 ? 使用泛型的好处是什么? 泛型是Java SE 1.5的新特性,泛型的本质是参数化类...

  • 面试题

    React组件的渲染流程是什么? 使用 React.createElement或 JSX编写 React组件,实际...

  • iOS 强大的泛型

    文章围绕一下五点进行介绍: 泛型是什么为什么要用泛型泛型怎么用泛型进阶泛型的延伸使用 泛型(Generics)是什...

  • React组件Render Props VS HOC 设计模式

    React的设计模式有很多种,比如无状态组件/表现型组件,有状态组件/容器型组件,render模式组件,高阶组件等...

  • C++模板初步

    泛型:指在多种数据类型上皆可操作的含义。泛型编程的代表作品STL是一种高效、泛型、可交互操作的软件组件 泛型编程最...

  • Boolan C++ 笔记四

    泛型编程泛型编程的代表作品STL是一种高效、泛型、可交互操作的软件组件。STL以迭代器(Iterators)和容器...

网友评论

      本文标题:React 泛型组件是什么?

      本文链接:https://www.haomeiwen.com/subject/aggqydtx.html