相关文章推荐
豪爽的篮球  ·  Qpid ...·  2 年前    · 
面冷心慈的菠萝  ·  java ...·  2 年前    · 

React 中使用TypeScript

Typescript:与React functional component中接受道具的混淆

浅谈React的React.FC与React.Component的使用

一、定义时 props的类型已知

将类型添加到函数参数

interface TodoListItemProps { 
    todo: { 
        text:string 
        complete:boolean 
const TodoListItem = ({ todo }: TodoListItemProps) => {
    console.log(todo)
    return ( 
    // ... 

将类型作为泛型参数添加到FC类型

interface TodoListItemProps { 
    todo: { 
        text:string 
        complete:boolean 
const TodoListItem: React.FC<TodoListItemProps> = ({ todo }) => {
    return( 
        // ... 

1、将类型添加到函数参数

interface IProps {
  name: string
const App = (props: IProps) => {
  const {name} = props;
  return (
    <div className="App">
      <h2>{name}</h2>
    </div>
export default App;

2、将类型作为泛型参数添加到FC类型

使用React.FunctionComponent<P={}>来定义,也可以使用其简写React.FC<P={}>。 它是在ts中使用的一个泛型接口,可以接收一个参数,参数表示props的类型,这个参数不是必须的。

使用React.FC来写 React 组件的时候,是不能用 setState(在类组件中使用)的,取而代之的是useState()、useEffect等 Hook API。

interface IProps {
  name: string
const App: React.FC<IProps> = (props) => {
//解构出 name 的值
  const {name} = props;
  return (
    <div className="App">
      <h2>{name}</h2>
    </div>
export default App;
const App: React.FunctionComponent<{ message: string }> = ({ message }) => (
    console.log('message:', message)
    return (
      <div>{message}</div>

检查react类型,可以看到:

type React.FC<P = {}> = React.FunctionComponent<P>
interface FunctionComponent<P = {}> { 
    (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null; 
    propTypes?: WeakValidationMap<P>; 
    contextTypes?: ValidationMap<any>; 
    defaultProps?: Partial<P>; 
    displayName?: string; 

与第一种普通的函数声明方法相比:

1、React.FC 对静态属性:displayName,propTypes 和 defaultProps 提供了类型检查和自动补全(注意:defaultProps与React.FC结合使用会存在一些问题)。

2、React.FC 显式地定义了返回类型,其他方式是隐式推导的。

3、React.FC 为 children 提供了隐式的类型(ReactElement | null)。

4、当使用这种形式来定义函数组件时,props中默认会带有children属性,它表示该组件在调用时,其内部的元素。举例如下:

App.tsx

import Child1 from "./child1";
import Child2 from "./child2";
interface IProps {
  name: string;
const App: React.FC<IProps> = (props) => {
//其他组件使用App组件,从其传入的 props里,解构出 name的值
  const { name } = props;
  return (
  //将 name的值传给子组件
    <Child1 name={name}>
      <Child2 name={name} />
      TypeScript
    </Child1>
export default App;

Child1.tsx

在Child1组件中打印了children属性,它的值是一个数组,包含Child2对象和后面的文本:

interface IProps {
  name: string;
const Child1: React.FC<IProps> = (props) => {
  const { name, children } = props;
  console.log(children);
  return (
    <div className="App">
      <h2>{name}</h2>
    </div>
export default Child1;

二、定义时 props的类型未知

如果在定义组件时不知道props的类型,由使用该组件时传入的参数决定,所以只有使用时才知道props的类型,那么定义组件时 就用泛型来定义props的类型。

1、用function定义的函数组件

MyComponent.tsx

// 定义组件
function MyComponent<P>(props: P) {
  return (
    <span>{props}</span>

page.tsx

// 在使用组件时定义参数类型
type IProps = { name: string; age: number; };
<MyComponent<IProps> name="React" age={18} />;          // Success
<MyComponent<IProps> name="TypeScript" age="hello" />;  // Error

2、用箭头函数定义的函数组件

必须使用extends关键字来定义泛型参数,才能被成功解析:

const MyComponent = <P extends any>(props: P) => {
  return (
    <span>{props}</span>

直接调用会报错:

const MyComponent = <P>(props: P) => {
  return (
    <span>{props}</span>
复制代码
分类:
前端
标签: