• 组件声明
    1、类组件:

      React.Component<P, S={}> 和 React.PureComponent<P, S={} SS={}>;
      import React, {PureComponent, Component} from "react";
      interface propsType {
          name: string
      }
      interface stateType {
          id: number
      }
      ......
      class App extends React.Component<propsType, stateType>{
          ......
      }
      class App React.PureComponent<propsType, stateType>{
          ......
      }
    
      React.Component 和 React.PureComponent 的区别在于 PureComponent 在 shouldComponentUpdate 只进行浅层的比较,只要外层的对象不发生变化就不会触发 render,减少了不必要的 virtual DOM 的 diff 和重新生成的过程,但缺点就是不适合在含有多层嵌套对象的 state 和 props 中(数据嵌套导致页面得不到更新),像表单等复杂组件中,将组件拆分成简单的 PureComponent,使得组件变得易于维护;而 Component 父组件的 state 和 props 更新时,子组件都会更新,浪费性能。
      如果在定义组件的时候不确定组件的props类型,只有在调用的时候才知道组件类型,就可以用泛型进行组建的定义了。
    
      class MyComponent<P> extends React.Component<P> {
          internalProp: P;
          constructor(props: P) {
              super(props);
                  this.internalProp = props;
              }
          render() {
                  return (
                      <span>hello world</span>
                  );
              }
          }
          // 使用组件
          type IProps = { name: string; age: number; };
          <MyComponent<IProps> name="React" age={18} />;          // Success
          <MyComponent<IProps> name="TypeScript" age="hello" />;  // Error
    

2、函数组件
书写方式有直接函数声明的方式和 React.FunctionComponent/React.FC<P={}> 来定义;

    `type React.FC<P = {}> = React.FunctionComponent<P>`
    import Child1 from "./child1";
    import Child2 from "./child2";
    interface IProps {
        name: string;
    }
    const App: React.FC<IProps> = (props) => {
        const { name } = props;
        return (
            <Child1 name={name}>
                <Child2 name={name} />
                TypeScript
            </Child1>
        );
    };
    export default App;
    // 其中 cheild1 组件的 props 中有 name 和 children 的属性,children 是一个数组,包含了 child2 对象和后面的文本;
    当使用箭头函数的方式进行定义的时候需要注意必须使用 extends 关键字来定义泛型参数才可以被解析成功;

    const MyComponent = <P extends any>(props: P) {
        return (
            <span>
                {props}
            </span>
        );
    }
    // 普通函数
    function MyComponent<P>(props: P) {
            return (
                <span>
                    {props}
                </span>
            );
    }
    // 使用组件
    type IProps = { name: string; age: number; };
    <MyComponent<IProps> name="React" age={18} />;          // Success
    <MyComponent<IProps> name="TypeScript" age="hello" />;  // Error

3、react 内置类型简介
JSX.Element 是 ReactElement 的子类型,没有添加属性,两者是等价的,可以相互赋值;
JSX.Element 可以通过执行 React.createElement 或是转译 JSX 获得:

    const jsx = <div>Lbxin</div>
    const ele = React.createElement("div", null, "Lbxin");

4、React Hooks
useState: 默认情况下 React 会根据 statue 的初始值进行自动推断 statue 和更新函数的类型;

    const [count, setCount] = useState<number>(1)  //已知 state 的类型;
    const [count, setCount] = useState<number | null>(null); ` //初始值为 null 则需显示的设置 state 的类型;
    const [user, setUser] = React.useState<IUser>({} as IUser);//初始化为空对象则需断言处理,断言处理是为了避免后续的代码依赖这个对象,所以在使用前进行断言初始化 user 的值,否则会报错;