在 React 中使用键盘控制 UI。如何正确做?

问题描述 投票:0回答:1

我想使用键盘控制我的应用程序 UI,但我不知道如何实现。 (视频播放器应用程序)我有 redux 商店,我将状态设置为控件。然后它通过 props 传递状态。我的方向正确吗?

我有组件 PlayerUI,它将状态作为 props 传递给 PlayerUIBottomBar

const PlayerUI = ({ channels, actualChannel, hlsQualityLevels }: IProps) => {

...

 const handleKeyUp = async (e: KeyboardEvent) => {
        if (e.key === "ArrowUp") {
            dispatch(playerUIActions.setActualEpgIndex(0))
            dispatch(playerUIActions.decrementChannelToChangeIndex());
        }
        if (e.key === "ArrowDown") {
            dispatch(playerUIActions.setActualEpgIndex(0))
            dispatch(playerUIActions.incrementChannelToChangeIndex());
        }
        if (e.key === "ArrowLeft") {
            dispatch(playerUIActions.decrementActualEpgIndex())
        }
        if (e.key === "ArrowRight") {
            dispatch(playerUIActions.incrementActualEpgIndex())
        }
        dispatch(playerUIActions.setIsMenuVisible(true));
    }
useEffect(() => {
        dispatch(getChannelsAsync());
        window.addEventListener("mousemove", setIsMenuVisible);
        window.addEventListener("keyup", handleKeyUp);
        return () => { window.removeEventListener("mousemove", setIsMenuVisible); window.removeEventListener("keyup", handleKeyUp); }
    }, []);

return (
        <div className={`${playerUIState.isMenuUIVisible ? "opacity-100" : "opacity-0"} transition-opacity duration-500`}>
            <PlayerUITopBar hlsQualityLevels={hlsQualityLevels} />
            <PlayerUIBottomBar channels={channels} isScrollToEpgSmooth={isScrollToEpgSmooth} selectedChannelIndex={playerUIState.channelToChangeIndex} isMenuVisible={playerUIState.isMenuUIVisible} />
        </div>
    )

}

组件PlayerUIBottomBar。在这个组件中,我做的第一件事是将列表滚动到选定的频道

export const PlayerUIBottomBar = ({ channels, isScrollToEpgSmooth = false, selectedChannelIndex, isMenuVisible }: IProps) => {
    const scrollChannel = (index: number, smooth: boolean = true) => {
        const channelToScrollElem = document.getElementById(index.toString());
        if (channelToScrollElem) {
            channelToScrollElem.scrollIntoView({
                behavior: smooth ? "smooth" : "instant"
            });
        }
    };
    if (isMenuVisible)
        {
            scrollChannel(selectedChannelIndex, true);}
    else
        setTimeout(() => {
            scrollChannel(selectedChannelIndex, false);
        }, 500);

return (
{channels
                        .filter((x) => x.enabled)
                        .map((channel, index) => (
                            <PlayerChannel
                                key={channel.ch_id}
                                channel={channel}
                                index={index}
                                handleClickChangeVideo={handleClickChangeVideo}
                                epgIndex={playerUIState.actualEpgIndex}
                                isSmoothScrollToEpg={isScrollToEpgSmooth}
                            />
}
)
}

通过 props 传递状态是否是正确的方法?我应该以不同的方式处理这个问题吗?例如。 useeffect 和依赖表对状态变化做出反应,然后滚动到选定的通道?

reactjs react-redux
1个回答
0
投票

在使用 Redux 进行状态管理的 React 应用程序中,如果状态已经存储在 Redux 存储中,则通常不需要通过 props 将状态传递给子组件。 Redux 提供了一个集中存储来管理应用程序的状态,任何组件都可以直接访问该状态,而无需通过组件层次结构向下传递。

这是在 React 中使用 Redux 的一般方法:

  1. 使用化简器和操作定义 Redux 存储来管理应用程序的状态。

  2. 在应用程序的顶层使用 React-Redux 的组件,使 Redux 存储可供所有组件使用。

  3. 使用 React-Redux 提供的连接函数或钩子(如

    useSelector
    useDispatch
    )将你的组件连接到 Redux 存储。

  4. 直接在组件内访问状态并调度操作。

要为您的应用程序 UI(包括视频播放器)实现键盘控制,您可以按照以下常规步骤操作:

  1. 定义 Redux 操作: 创建 Redux 操作以根据键盘输入更新 UI 控件的状态。例如,您可能有诸如togglePlay、seekForward、seekBackward、toggleFullScreen 等操作。

  2. 实现 Redux 减速器: 编写减速器来处理这些操作并在 Redux 存储中相应地更新 UI 控件状态。

  3. 将组件连接到 Redux: 使用 React-Redux 的 connect 函数或 useSelector 和 useDispatch 等挂钩将您的 UI 组件(包括视频播放器组件)连接到 Redux 存储。

  4. 处理键盘事件:在组件层次结构中的适当级别(通常是顶级组件或特定容器组件)添加键盘事件(例如 keydown 或 keyup)的事件侦听器。

  5. 调度 Redux 操作:当相关键盘事件发生时,调度相应的 Redux 操作来更新 Redux 存储中的 UI 控件状态。

  6. 根据状态更改更新 UI: 确保您的 UI 组件订阅了 Redux 存储中的相关状态切片,并根据 UI 控件状态的更改更新其外观或行为。

通过遵循这种方法,您可以避免通过多层组件向下传递状态的需要,从而使您的代码更干净且更易于维护。此外,它还有助于使组件更加解耦,因为它们不需要了解父级的状态结构。

© www.soinside.com 2019 - 2024. All rights reserved.