zoukankan      html  css  js  c++  java
  • 3分钟掌握hook在typescript中的姿势

    3分钟掌握hook在typescript中的姿势

    hook结合typescript可以说是很香了。本文主要介绍hook结合typescript 如何使用,享受ts带给我们的编辑器提示和类型约束

    useState

    useState如果初始值不是null/undefined的话,是具备类型推导能力的,根据传入的初始值推断出类型;初始值是 null/undefined的话则需要传递类型定义才能进行约束。一般情况下,还是推荐传入类型(通过useState的第一个泛型参数)。

    // 这里ts可以推断 value的类型并且能对setValue函数调用进行约束
    const [value, setValue] = useState(0);
    
    interface MyObject {
      foo: string;
      bar?: number;
    }
    
    // 这里需要传递MyObject才能约束 value, setValue
    // 一般情况下推荐传入类型
    const [value, setValue] = useState<MyObject>(null);

    useContext

    useContext一般根据传入的Context的值就可以推断出返回值。不需要显示传递类型

    type Theme = 'light' | 'dark';
    // 我们在createContext就传了类型了
    const ThemeContext = createContext<Theme>('dark');
    
    const App = () => (
      <ThemeContext.Provider value="dark">
        <MyComponent />
      </ThemeContext.Provider>
    )
    
    const MyComponent = () => {
        // useContext根据ThemeContext推断出类型,这里不需要显示传
      const theme = useContext(ThemeContext);
      return <div>The theme is {theme}</div>;

    useEffect useLayoutEffect

    没有返回值,无需传递类型

    useCallback useMemo

    useMemo无需传递类型,根据函数的返回值就能推断出类型

    useCallback无需传递类型,根据函数的返回值就能推断出类型。但是注意函数的入参需要定义类型,不然就是推断为any了!

    const value = 10;
    // 推断出result是number类型
    const result = useMemo(() => value * 2, [value]);
    
    const multiplier = 2;
    // 推断出 (value: number) => number
    // 注意函数入参value需要定义类型
    const multiply = useCallback((value: number) => value * multiplier, [multiplier]);

    useRef

    useRef传非空初始值的时候可以推断类型,同样也可以通过传入第一个泛型参数来定义类型,约束ref.current的类型。

    const MyInput = () => {
      // 这里约束inputRef是一个html元素
      const inputRef = useRef<HTMLInputElement>(null);
      return <input ref={inputRef} />
    }
    // 自动推断出 myNumberRef.current 是number类型
    const myNumberRef = useRef(0);
    myNumberRef.current += 1;

    useReducer

    只需要对传入useReducer的reducer函数的入参stateaction进行类型约束就能够推断出来

    interface State {
      value: number;
    }
    
    type Action =
      | { type: 'increment' }
      | { type: 'decrement' }
      | { type: 'incrementAmount'; amount: number };
    
    const counterReducer = (state: State, action: Action) => {
      switch (action.type) {
        case 'increment':
          return { value: state.value + 1 };
        case 'decrement':
          return { value: state.value - 1 };
        case 'incrementAmount':
          return { value: state.value + action.amount };
        default:
          throw new Error();
      }
    };
    
    // 这里可以推断出state为State类型
    const [state, dispatch] = useReducer(counterReducer, { value: 0 });
    
    //能够约束传入dispatch的参数,符合Action类型
    dispatch({ type: 'increment' });
    dispatch({ type: 'decrement' });
    dispatch({ type: 'incrementAmount', amount: 10 });
    
    // TypeScript compilation error
    dispatch({ type: 'invalidActionType' });

    useImperativeHandle

    useImperativeHandle一般比较少用,一般用来选择函数组件对外暴露ref属性被调用,需要配合forwardRef使用。

    如下例子。需要定义对外暴露的接口MyInputHandles,函数组件使用React.RefForwardingComponent对外暴露的接口调用作为泛型参数。然后就会得到约束了

    // MyInputHandles 需要给父组件的useRef作为类型使用 和 RefForwardingComponent作为泛型参数传入约束
    export interface MyInputHandles {
      focus(): void;
    }
    
    // 使用RefForwardingComponent 类型进行定义组件,第一个泛型参数是对外暴露的handle,第二个是Props
    const MyInput: RefForwardingComponent<MyInputHandles, MyInputProps> = (
      props,
      ref
    ) => {
      const inputRef = useRef<HTMLInputElement>(null);
    
      useImperativeHandle(ref, () => ({
        // 这里的返回会自动使用MyInputHandles进行类型约束
        focus: () => {
          if (inputRef.current) {
            inputRef.current.focus();
          }
        },
      }));
    
      return <input {...props} ref={inputRef} />;
    };
    
    // 函数组件必须使用forwardRef才能让外部组件使用该组件的ref
    export default forwardRef(MyInput);
    // 父组件
    const Autofocus = () => {
      // 能够约束 myInputRef.current的类型
      const myInputRef = useRef<MyInputHandles>(null);
    
      useEffect(() => {
        if (myInputRef.current) {
          myInputRef.current.focus();
        }
      });
    
      return <MyInput ref={myInputRef} />
    }

    参考:

    React Hooks in TypeScript

    本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

  • 相关阅读:
    KVM/QEMU简介
    编辑器制作的一些资源
    HRBEU ACM 图论 1006
    zoj 2001
    HRBEU equal
    zoj Integer Inquiry
    HRBEU 字符串 1003
    poj 2736
    SDUT_DP 1003
    zoj Martian Addition
  • 原文地址:https://www.cnblogs.com/sexintercourse/p/15663869.html
Copyright © 2011-2022 走看看