React Typescript

121 阅读2分钟

useState

TS类型

// 类型
type SetStateAction<S> = S | ((prevState: S) => S);
type Dispatch<A> = (value: A) => void;

function useState<S = undefined>(): [S | undefined, Dispatch<SetStateAction<S | undefined>>];
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];

useState使用

useReducer

TS类型

// 类型
type Reducer<S, A> = (prevState: S, action: A) => S;
type ReducerState<R extends Reducer<any, any>> = R extends Reducer<infer S, any> ? S : never;
type ReducerAction<R extends Reducer<any, any>> = R extends Reducer<any, infer A> ? A : never;

function useReducer<R extends Reducer<any, any>>(
    reducer: R,
    initialState: ReducerState<R>,
    initializer?: undefined
): [ReducerState<R>, Dispatch<ReducerAction<R>>];

注:还有其他多态

基本使用

import { useReducer } from "react";

const initialState = { count: 0 };

type ACTIONTYPE =
  | { type: "increment"; payload: number }
  | { type: "decrement"; payload: string };
// 类型申明
function reducer(state: typeof initialState, action: ACTIONTYPE) {
  switch (action.type) {
    case "increment":
      return { count: state.count + action.payload };
    case "decrement":
      return { count: state.count - Number(action.payload) };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: "decrement", payload: "5" })}>
        -
      </button>
      <button onClick={() => dispatch({ type: "increment", payload: 5 })}>
        +
      </button>
    </>
  );
}

useReducer使用

更好封装

import type { useReducer } from "react";

const initialState = { count: 0 };

type InitialState = typeof initialState;
type ACTIONTYPE =
  | { type: "increment"; payload: number }
  | { type: "decrement"; payload: string };
type CountReducer = Reducer<InitialState, ACTIONTYPE>;

const reducer: CountReducer = (state, action) => {
  switch (action.type) {
    case "increment":
      return { count: state.count + action.payload };
    case "decrement":
      return { count: state.count - Number(action.payload) };
    default:
      throw new Error();
  }
};

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: "decrement", payload: "5" })}>
        -
      </button>
      <button onClick={() => dispatch({ type: "increment", payload: 5 })}>
        +
      </button>
    </>
  );
}

useEffect

TS类型

// 类型
declare const UNDEFINED_VOID_ONLY: unique symbol;
// Destructors are only allowed to return void.
type Destructor = () => void | { [UNDEFINED_VOID_ONLY]: never };
type EffectCallback = () => (void | Destructor);
type DependencyList = ReadonlyArray<unknown>;

function useEffect(effect: EffectCallback, deps?: DependencyList): void;

useLayoutEffect

TS类型

declare const UNDEFINED_VOID_ONLY: unique symbol;
// Destructors are only allowed to return void.
type Destructor = () => void | { [UNDEFINED_VOID_ONLY]: never };
type EffectCallback = () => (void | Destructor);
type DependencyList = ReadonlyArray<unknown>;

function useLayoutEffect(effect: EffectCallback, deps?: DependencyList): void;

uesRef

TS类型

interface RefObject<T> {
    // 重点只读
    readonly current: T | null;
}
interface MutableRefObject<T> {
    current: T;
}

function useRef<T>(initialValue: T): MutableRefObject<T>;
// 如果初始值设置为null则命中一下重载函数
function useRef<T>(initialValue: T|null): RefObject<T>;
function useRef<T = undefined>(): MutableRefObject<T | undefined>;

注: In TypeScript, useRef returns a reference that is either read-only or mutable, depends on whether your type argument fully covers the initial value or not. Choose one that suits your use case.

应用场景

获取dom

ref-dom

获取实时值

temp-value

useImperativeHandle

TS类型

interface RefObject<T> {
        readonly current: T | null;
    }
// Bivariance hack for consistent unsoundness with RefObject
type RefCallback<T> = { bivarianceHack(instance: T | null): void }["bivarianceHack"];
type Ref<T> = RefCallback<T> | RefObject<T> | null;

function useImperativeHandle<T, R extends T>(ref: Ref<T>|undefined, init: () => R, deps?: DependencyList): void;

应用

import { forwardRef, useImperativeHandle, useRef } from "react";

function App() {
  // 引入类型
  const countdownRef = useRef<CountdownHandle>(null);
  const onclick = () => {
    countdownRef.current?.start();
    console.log(countdownRef.current?.test);
  };

  return (
    <div className="App">
      <div onClick={onclick}>点击</div>
      <Countdown ref={countdownRef} />
    </div>
  );
}

export type CountdownHandle = {
  start: () => void;
  test: string;
};

type CountdownProps = {};

const Countdown = forwardRef<CountdownHandle, CountdownProps>((props, ref) => {
  useImperativeHandle(ref, () => ({
    // start() has type inference here
    start() {
      console.log(1111122222);
    },
    test: "11111",
  }));

  return <div>Countdown</div>;
});

export default App;

useImperativeHandle使用

useMemo

TS类型

function useMemo<T>(factory: () => T, deps: DependencyList | undefined): T;

应用

import { useMemo } from "react";

type MemoObj = {
  age: number;
  name: string;
};

function App() {
  const memoPersonMsg = useMemo<MemoObj>(() => {
    return {
      age: 1,
      name: "ttl",
    };
  }, []);

  return (
    <div className="App">
      <div>{memoPersonMsg.age}</div>
      <div>{memoPersonMsg.name}</div>
    </div>
  );
}

export default App;

useCallback

TS类型

function useCallback<T extends Function>(callback: T, deps: DependencyList): T;

注:暂时没想到类型必要性;入参extends Function

后续

持续更新