reactjs - useReducer 中返回参数的通用类型

标签 reactjs typescript generics react-hooks

我正在编写一个自定义 Hook 来从 API 获取一些数据。如果可能的话,我希望返回的数据是类型安全的。这可以用泛型来完成吗?

type Action = { type: 'PENDING' } | { type: 'SUCCESS'; payload: any } | { type: 'FAIL' };

interface State {
  isLoading: boolean;
  isError: boolean;
  data: any;
}

const dataFetchReducer = (state: State, action: Action): State => {
  switch (action.type) {
    case 'PENDING':
      return {
        ...state,
        isLoading: true,
      };
    case 'SUCCESS': {
      return {
        ...state,
        isLoading: false,
        isError: false,
        data: action.payload,
      };
    }
    case 'FAIL':
      return {
        ...state,
        isLoading: false,
        isError: true,
      };
    default:
      throw new Error('Action not supported');
  }
};

const baseUrl = 'http://localhost:4000';

function useDataFetchFromAPI(initUrl: string, initData: any) {
  const [url, setUrl] = useState(`${baseUrl}${initUrl}`);
  const [state, dispatch] = useReducer(dataFetchReducer, {
    isLoading: false,
    isError: false,
    data: initData,
  });

  // effect only runs if url changes
  // see deps array (2nd argument)
  useEffect(() => {
    const fetchData = async () => {
      dispatch({ type: 'PENDING' });
      try {
        const result = await axios(url);
        dispatch({ type: 'SUCCESS', payload: result.data });
      } catch (error) {
        dispatch({ type: 'FAIL' });
      }
    };
    fetchData();
  }, [url]);
  const executeFetch = (url: string) => {
    setUrl(url);
  };
  return { ...state, executeFetch };
}

用法为useDataFetchFromAPI('url', []) .

我想你可以做类似 useDataFetchFromAPI < SomeType > () 的事情并通过它,但我不确定实现情况。

最佳答案

import axios, { AxiosPromise } from 'axios';
import { FC, useEffect, useReducer, useState } from 'react';

type Action<T> = { type: 'PENDING' } | { type: 'SUCCESS'; payload: T } | { type: 'FAIL' };

interface State<T> {
    isLoading: boolean;
    isError: boolean;
    data: T;
}

const createDataFetchReducer = <T>() => (state: State<T>, action: Action<T>): State<T> => {
    switch (action.type) {
        case 'PENDING':
            return {
                ...state,
                isLoading: true,
            };
        case 'SUCCESS': {
            return {
                ...state,
                isLoading: false,
                isError: false,
                data: action.payload,
            };
        }
        case 'FAIL':
            return {
                ...state,
                isLoading: false,
                isError: true,
            };
        default:
            throw new Error('Action not supported');
    }
};

const baseUrl = 'http://localhost:4000';

function useDataFetchFromAPI<T>(initUrl: string, initData: T) {
    const [url, setUrl] = useState(`${baseUrl}${initUrl}`);
    const dataFetchReducer = createDataFetchReducer<T>();
    const [state, dispatch] = useReducer(dataFetchReducer, {
        isLoading: false,
        isError: false,
        data: initData,
    });

    // effect only runs if url changes
    // see deps array (2nd argument)
    useEffect(() => {
        const fetchData = async () => {
            dispatch({ type: 'PENDING' });
            try {
                const axiosPromise: AxiosPromise<T> = axios(url);
                const result = await axiosPromise;
                dispatch({ type: 'SUCCESS', payload: result.data });
            } catch (error) {
                dispatch({ type: 'FAIL' });
            }
        };
        fetchData();
    }, [url]);
    const executeFetch = (url: string) => {
        setUrl(url);
    };
    return { ...state, executeFetch };
}

const MyComponent: FC<{}> = props => {
    type Response = { foo: number; }
    const x = useDataFetchFromAPI<Response>('/foo', {
        foo: 1
    });
    x.data.foo;

    return null;
};

关于reactjs - useReducer 中返回参数的通用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55396438/

相关文章:

javascript - 给 SVG 文本一个带有 rect 的背景

generics - 具有高阶函数的 Kotlin 合约

javascript - 无法读取未定义的属性 'indexOf' - React-sortable-hoc

reactjs - 在 React Redux 存储中存储文件对象的最佳方式(从 DropZone 上传文件?)

angular - Angular 应用程序的剧作家同步问题

TypeScript:获取对象本身内部的对象键类型

相同类型的 Java 泛型约束

c# - 在其成员函数之一中进一步约束泛型类c#

javascript - 在 React 中渲染最多 X 个元素

javascript - 如何确保 React 中不会出现异常错误或任何类型的导致应用程序停止执行或崩溃的错误