typescript 获取“类型无法分配给类型FunctionComponent< Props>“和“类型缺少类型”React Element〈any,any>“的以下属性”

6fe3ivhb  于 2022-12-24  发布在  TypeScript
关注(0)|答案(1)|浏览(787)

我尝试将TypeScript添加到我的代码中,但我不断地遇到一个错误,我认为这与我的Props类型或其他东西有关。整个错误如下:

Type '({ volume, onload, isMuted, src, mediaType, ...config }: PropsWithChildren<Props>) => { howl: Howl | undefined; isMuted: boolean | undefined; volume: number; ready: boolean; pause: () => void; play: () => void; fade: (from: number, to: number, duration: number) => void; seek: () => number | undefined; duration: () =...' is not assignable to type 'FunctionComponent<Props>'.
Type '{ howl: Howl | undefined; isMuted: boolean | undefined; volume: number; ready: boolean; pause: () => void; play: () => void; fade: (from: number, to: number, duration: number) => void; seek: () => number | undefined; duration: () => number | undefined; }' is missing the following properties from type 'ReactElement<any, any>': type, props, keyts(2322)

我正在创建我的Props类型,然后从泛型FunctionComponent中推断出我的函数的参数。我怀疑mapDispatchToProps可能是这里的问题所在。我的问题是我无法从错误消息中推断出问题所在。

import { useState, useEffect, useRef, FunctionComponent } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators, Dispatch } from 'redux';
import { Howl } from 'howler';

import { getSignedMediaURL } from '../../services/meditations';
import { SetHasConnectivity } from 'src/store/user/actions';

const mapDispatchToProps = (dispatch: Dispatch) =>
    bindActionCreators({ SetHasConnectivity }, dispatch);

const noop = () => {};

type Props = {
    src: string | null;
    onload?: () => void;
    volume?: number;
    isMuted?: boolean;
    mediaType: 'soundscape' | 'meditation' | 'other';
    loop?: boolean;
    onend?: () => void;
    onstop?: () => void;
} & ReturnType<typeof mapDispatchToProps>;

const useMeditation: FunctionComponent<Props> = ({ volume = 1, onload = noop, isMuted, src, mediaType, ...config }) => {
    const player = useRef<Howl>();
    const soundId = useRef<number>();

    const [ready, setReady] = useState(false);

    const onSoundLoad = () => {
        if (player.current) {
            player.current.volume(volume);
            setReady(true);
            onload();
        }
    };

    useEffect(() => {
        if (src) {
            (async function () {
                let url = src;

                if (mediaType === 'soundscape' || mediaType === 'meditation') {
                    try {
                        const response = await getSignedMediaURL(src, mediaType);
                        url = response.body.url;
                    } catch (error) {
                        console.log('Test');
                    }
                }

                player.current = new Howl({
                    src: [url],
                    html5: true,
                    volume: 0,
                    onload: onSoundLoad,
                    ...config,
                });
            })();
        } else {
            setReady(true);
        }

        return () => {
            if (player.current) {
                player.current.stop();
            }
        };
    }, []); // eslint-disable-line

    useEffect(() => {
        if (player.current) {
            player.current.volume(volume);
        }
    }, [volume]);

    useEffect(() => {
        if (player.current) {
            if (isMuted) {
                player.current.mute(true, soundId.current);
            } else {
                player.current.mute(false);
            }
        }
    }, [isMuted]);

    const pause = () => {
        if (player.current) {
            player.current.pause();
        }
    };

    const play = () => {
        if (player.current) {
            soundId.current = player.current.play();
        }
    };

    const fade = (from: number, to: number, duration: number) => {
        if (player.current) {
            if (!player.current.playing()) {
                play();
            }

            player.current.fade(from, to, duration, soundId.current);
        }
    };

    const seek = () => {
        if (player.current) {
            return player.current.seek();
        }

        return;
    };

    const duration = () => {
        if (player.current) {
            return player.current.duration();
        }

        return;
    };

    return {
        howl: player.current,
        isMuted,
        volume,
        ready,

        pause,
        play,
        fade,

        seek,
        duration,
    };
}

export connect(null, mapDispatchToProps)(useMeditation);
bvhaajcl

bvhaajcl1#

React组件必须返回一个JSX元素(本质上是一个HTML片段)或null。您的useMeditation不是一个组件-它是一个返回对象的自定义钩子。
此类型注解不正确:

const useMeditation: FunctionComponent<Props> = ({ volume = 1, onload = noop, isMuted, src, mediaType, ...config }) => {

它应该是:

const useMeditation = ({ volume = 1, onload = noop, isMuted, src, mediaType, ...config }: Props) => {

connect高阶组件不能用在钩子上,只能用在组件上。
你需要使用useDispatch钩子来代替。我没有看到你实际上在哪里调度这个动作。但是它应该看起来像这样。

// Same as before, but delete the `ReturnType<typeof mapDispatchToProps>`
type Props = { /* ... */ }

const useMeditation = ({ volume = 1, onload = noop, isMuted, src, mediaType, ...config }: Props) => {

    // Get access to the dispatch function.
    const dispatch = useDispatch();

    // Dispatch your action.
    const someFunction = () => {
        dispatch(SetHasConnectivity(true));
    }

    /* ... rest of the hook ... */
}

// No need to use `connect` or anything else here, just export it.
export default useMeditation;

相关问题