मेरे पास निम्न http हुक है:

export const useHttp = <T,>(initUrl: string, initData: T) => {
    const [url, setUrl] = useState(initUrl);
    const [state, dispatch] = useReducer(fetchReducer, {
        isLoading: false,
        error: '',
        data: initData
    });

    useEffect(() => {
        let cancelRequest = false;

        const fetchData = async (cancelRequest: boolean = false) => {
            if (!url) return;

            dispatch({ type: 'API_REQUEST'});
            try {
                const responsePromise: AxiosPromise<T> = axios(url);
                const response = await responsePromise;
                if (cancelRequest) return;
                dispatch({ type: 'API_SUCCESS', payload: response.data });
            } catch (e) {
                console.log("Got error", e);
                dispatch({ type: 'API_ERROR', payload: e.message });
            }
        };
        fetchData(cancelRequest);

        return () => {
            cancelRequest = true;
        }

    }, [url]);

    const executeFetch = (url: string) => {
        setUrl(url);
    };

    return { ...state, executeFetch}
};

रेड्यूसर:

const fetchReducer = <T,>(state: IState<T>, action: TAction<T>): IState<T> => {
    switch (action.type) {
        case 'API_REQUEST':
            return {
                ...state,
                isLoading: true
            };
        case 'API_SUCCESS':
            return {
                ...state,
                data: action.payload,
                isLoading: false,
                error: ''
            };
        case 'API_ERROR':
            console.error(`Triggered: ${API_ERROR}, message: ${action.payload}`);
            return {
                ...state,
                error: action.payload,
                isLoading: false,
            };
        default:
            throw Error('Invalid action');
    }
};

क्रियाएँ:

export interface IApiSuccess<T> {
    type: types.ApiSuccess,
    payload: T;
}
export type TAction<T> = IApiRequest | IApiSuccess<T> | IApiError;

इस तरह उपयोग करना:

const { data, error, isLoading, executeFetch } = useHttp<IArticle[]>('news', []);

return (
        <>
            <div className={classes.articleListHeader}>
                <h1>Article List</h1>
                <small className={classes.headerSubtitle}>{data.length} Articles</small>
            </div>
            <ul>
                {data.map(article => <Article article={article}/>)}
            </ul>
        </>
    )

मेरा TS मुझ पर चिल्लाता है क्योंकि मैं data वेरिएबल का उपयोग कर रहा हूं: Object is of type 'unknown'. TS2571

मैंने useHttp का प्रकार निर्दिष्ट किया है जो IArtlce[] है। मुझे क्या याद आ रही है कोई विचार?

अपडेट: मैंने अपने रेड्यूसर के लिए रिटर्न टाइप जोड़ने की कोशिश की:

interface HttpReducer<T> extends IState<T> {
    executeFetch: (url: string) => void
}

export const useHttp = <T,>(initUrl: string, initData: T): HttpReducer<T> => {

लेकिन मुझे मिलता है:

Type '{ executeFetch: (url: string) => void; error: string; isLoading: boolean; data: unknown; }' is not assignable to type 'HttpReducer<T>'.
1
TheUnreal 21 मार्च 2021, 11:44
state में एक प्रकार जोड़ने का प्रयास करें। या कस्टम हुक में वापसी प्रकार जोड़ें।
 – 
Ramesh Reddy
21 मार्च 2021, 11:57
state में टाइप जोड़ने का क्या मतलब है? मेरे राज्य पैरामीटर में IState<T> प्रकार है।
 – 
TheUnreal
21 मार्च 2021, 12:04
प्रश्न में इसका उल्लेख नहीं है ... क्या आपने रिटर्न प्रकार जोड़ने का प्रयास किया?
 – 
Ramesh Reddy
21 मार्च 2021, 12:06
fetchReducer कैसे टाइप किया जाता है?
 – 
thedude
21 मार्च 2021, 12:08
सुनिश्चित नहीं है कि मैं अपने मामले के लिए इस तरह का प्रकार कैसे जोड़ सकता हूं। उदाहरण के साथ मेरा प्रश्न अपडेट किया गया
 – 
TheUnreal
21 मार्च 2021, 12:17

1 उत्तर

सबसे बढ़िया उत्तर

मैं आपकी त्रुटि को पुन: प्रस्तुत करने में सक्षम था। आप उम्मीद कर रहे हैं कि useReducer हुक प्रारंभिक अवस्था के प्रकार के आधार पर राज्य के प्रकार का अनुमान लगाने में सक्षम होगा, लेकिन यह केवल IState<unknown> का अनुमान लगा रहा है।

useReducer के प्रकार परिभाषित हैं जैसे कि सामान्य तर्क रिड्यूसर का प्रकार है। राज्य के प्रकार का अनुमान ReducerState उपयोगिता प्रकार के साथ रिड्यूसर से लगाया जाता है। यह एक सामान्य रेड्यूसर की अपेक्षा नहीं कर रहा है और इसके साथ अच्छी तरह से काम नहीं करता है।

राज्य के बजाय हुक के T और रिड्यूसर के T के बीच कोई संबंध नहीं है। fetchReducer एक सामान्य कार्य है जिसका अर्थ है कि यह कोई भी IState ले सकता है और उसी प्रकार का IState लौटा सकता है। हम अपने हुक के IState<T> को संसाधित करने के लिए इस फ़ंक्शन का उपयोग कर सकते हैं, लेकिन राज्य के प्रकार का अनुमान लगाने के लिए हमें यह कहना होगा कि हमारा फ़ंक्शन केवल स्वीकार करेगा और वापस करेगा IState<T>.

आपको इसके लिए सामान्य useReducer सेट करना होगा:

const [state, dispatch] = useReducer<(state: IState<T>, action: TAction<T>) => IState<T>>( ...

सतह पर यह बहुत कुछ वैसा ही दिखता है जैसा अभी अनुमान लगाया जा रहा है, जो है:

const [state, dispatch] = useReducer<<T,>(state: IState<T>, action: TAction<T>) => IState<T>>(...

लेकिन अंतर गंभीर रूप से महत्वपूर्ण है। करंट एक सामान्य फ़ंक्शन का वर्णन करता है जबकि फिक्स एक फ़ंक्शन का वर्णन करता है जो केवल एक प्रकार का T लेता है - वह useHttp हुक का। यह भ्रामक है क्योंकि आप दोनों के लिए T का उपयोग कर रहे हैं। शायद यह देखना आसान है कि क्या हम एक का नाम बदलते हैं।

हमारे पास एक सामान्य कार्य था था:

export const useHttp = <Data,>(initUrl: string, initData: Data) => {
  const [url, setUrl] = useState(initUrl);
  const [state, dispatch] = useReducer<<T,>(state: IState<T>, action: TAction<T>) => IState<T>>(fetchReducer, {

हमें उस फ़ंक्शन के विशिष्ट उपयोग के मामले की आवश्यकता है:

export const useHttp = <Data,>(initUrl: string, initData: Data) => {
  const [url, setUrl] = useState(initUrl);
  const [state, dispatch] = useReducer<(state: IState<Data>, action: TAction<Data>) => IState<Data>>(fetchReducer, {

जब हम जानते हैं कि हमारा रेड्यूसर राज्य प्रकार IState<Data> है, तो हम जानते हैं कि data का प्रकार Data है।

अब useHttp<IArticle[]>() को कॉल करने से आपको एक data वैरिएबल IArticle[] मिलता है।

टाइपप्रति खेल का मैदान लिंक

2
Linda Paiste 21 मार्च 2021, 23:50