【问题标题】:Converting React useReducer to TypeScript将 React useReducer 转换为 TypeScript
【发布时间】:2021-04-01 20:26:35
【问题描述】:

我正在尝试将 useReducer 挂钩转换为 TypeScript, 它作为 useReducer 钩子可以正常工作,但在 TypeScript 中却不行。

这是我的代码,

import * as React from "react";

const JOKE_URL = "https://icanhazdadjoke.com/";

const initialState = { data: null, error: null, loading: true };
type ACTIONTYPE =
    | { type: "fetch" }
    | { type: "data"; data: object }
    | {type: "error"};

function fetchReducer(state: typeof initialState, action: ACTIONTYPE) {
    switch (action.type) {
        case 'fetch':
            return {
                ...state,
                loading: true,
            }

        case 'data':
            return {
                ...state,
                data: action.data,
                error: null,
                loading: false,
            }

        case 'error':
            return {
                ...state,
                error: 'Error fetching data. Try again',
                loading: false,
            }

        default:
            return state;
    }

}

function useFetch (url: string) {
    const [state, dispatch] = React.useReducer(
        fetchReducer,
        { data: null, error: null, loading: true }
    )

    React.useEffect(() => {
        dispatch({ type: 'fetch' })

        fetch(url, {
            headers: {
                accept: "application/json"
            }
        })
            .then((res) => res.json())
            .then((data) => dispatch({ type: 'data', data }))
            .catch((e) => {
                console.warn(e.message)
                dispatch({ type: 'error' })
            })
    }, [url])

    return {
        loading: state.loading,
        data: state.data,
        error: state.error
    }
}

export default function App() {
    const { loading, data, error } = useFetch(JOKE_URL);
    console.log(data);
    if (loading === true) {
        return <p>Loading</p>
    }
    if (error) {
        return (
            <React.Fragment>
                <p>{error}</p>
            </React.Fragment>
        )
    }
    return (
        <div>
            <h1>{data.joke}</h1>
        </div>
    );
}

我收到一些错误,例如: -> 类型参数 '(state: { data: null; error: null; loading: boolean; }, action: ACTIONTYPE) => { data: null;错误:空;加载:布尔值; } | {数据:对象;错误:空;加载:布尔值; } | {错误:字符串;加载:布尔值;数据:空; }' 不可分配给“ReducerWithoutAction”类型的参数。 TS2769 -> 预期 0 个参数,但得到 1 个。TS2554

【问题讨论】:

    标签: reactjs typescript reducers


    【解决方案1】:

    你应该为你的减速器设置返回类型并且一切正常,我也改变了你的一些状态和类型来清理你的代码:

    import * as React from "react";
    
    const JOKE_URL = "https://icanhazdadjoke.com/";
    
    const initialState = { loading: true };
    
    type initState ={
      data?: any,
      error?: string,
      loading: boolean
    }
    type ACTIONTYPE =
        | { type: "fetch" }
        | { type: "data"; data: object }
        | { type: "error"};
    
    function fetchReducer(state: initState, action: ACTIONTYPE):initState {
        switch (action.type) {
            case 'fetch':
                return {
                    ...state,
                    loading: true,
                }
    
            case 'data':
                return {
                    ...state,
                    data: action.data,
                    loading: false,
                }
    
            case 'error':
                return {
                    ...state,
                    error: 'Error fetching data. Try again',
                    loading: false,
                }
    
            default:
                return state;
        }
    
    }
    
    function useFetch (url: string) {
        const [state, dispatch] = React.useReducer(
            fetchReducer,
            initialState
        )
    
        React.useEffect(() => {
            dispatch({ type: 'fetch' })
    
            fetch(url, {
                headers: {
                    accept: "application/json"
                }
            })
                .then((res) => res.json())
                .then((data) => dispatch({ type: 'data', data }))
                .catch((e) => {
                    console.warn(e.message)
                    dispatch({ type: 'error' })
                })
        }, [url])
    
        return {
            loading: state.loading,
            data: state.data,
            error: state.error
        }
    }
    
    export default function App() {
        const { loading, data, error } = useFetch(JOKE_URL);
        console.log(data);
        if (loading) {
            return <p>Loading</p>
        }
        if (error) {
            return (
                <React.Fragment>
                    <p>{error}</p>
                </React.Fragment>
            )
        }
        return (
            <div>
                <h1>{data.joke}</h1>
            </div>
        );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-22
      • 2020-04-13
      • 1970-01-01
      • 2018-06-15
      • 2020-05-28
      • 1970-01-01
      • 2021-10-27
      • 1970-01-01
      相关资源
      最近更新 更多